How to serve media files on Django production environment? - python

In me settings.py file :-
DEBUG = False
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
STATIC_URL = '/static/'
LOGIN_URL = '/login/'
MEDIA_URL = '/media/'
In my urls.py file:-
urlpatterns += static(settings.STATIC_URL, document_root = settings.STATIC_ROOT)
urlpatterns += static(settings.MEDIA_URL, document_root = settings.MEDIA_ROOT)
When I am uploading the profile image then it is uploading to specified folder. but when i am visiting the user profile url then i am getting error like this in terminal
"GET /media/profile_images/a_34.jpg HTTP/1.1" 404 103
a_34.png is present in /media/profile_images/
then why it is not showing on browser and i am getting 404 error?

Django is not made to serve media file in production environment. You must configure the STATIC_ROOT settings and alias webserver to directly serve.
For example
If you are using apache web server in production, add the below to your virtualhost configuration
Alias /media/ /path/to/media_file/
<Directory /path/to/media_file/>
Order deny,allow
Allow from all
</Directory>
If you use Nginx you would have to use something like
location /media {
alias /path/to/media/file; # Change to your own media directory here.
access_log off;
}
Alternatively, you could also serve static files from AWS S3 or other cloud servers using django-storages

Django discourages to serve media files on production from the server. Use cloud services like amazon s3 to server your media files. See this Django doc serve media then give that path in MEDIA_URL.

You can use S3 Amazon for static and media files. It will be better.
Problem with S3 Amazon
Making the S3 bucket appear as part of the file system has terrible performance and fails randomly. When we are copying a lot of files it can take 10, 15, or 20 minutes for the copying to complete making deployments take a long time when they don’t need to. If we send these directly into S3 the same copy command takes about 1 minute to complete.
Solution
Subclass S3BotoStorage twice, one class for static files and the other for media files. This allows us to use different buckets and subdirectories for each type. (see: custom_storage.py)
Update settings
1. AWS_STORAGE_BUCKET_NAME needs to be bucket to hold static files and media files
2. MEDIAFILES_BUCKET
3. MEDIAFILES_LOCATION
4.DEFAULT_FILE_STORAGE
5.STATICFILES_BUCKET
6.STATICFILES_LOCATION
This is the subdirectory under the S3 bucket for the app
7.STATIC_URL
8.STATICFILES_STORAGE
Create custom_storage.py with the contents:
from django.utils.deconstruct import deconstructible
from storages.backends.s3boto import S3BotoStorage
from django.conf import settings
#deconstructible
class StaticS3Storage(S3BotoStorage):
bucket_name = settings.STATICFILES_BUCKET
location = settings.STATICFILES_LOCATION
#deconstructible
class MediaS3Storage(S3BotoStorage):
bucket_name = settings.MEDIAFILES_BUCKET
location = settings.MEDIAFILES_LOCATION
Sample settings.py.tmpl for updates settings (as mentioned above) based on my stack.json
MEDIAFILES_BUCKET = '<%= #node["apps_data"]["aws"]["buckets"]["bucket-name"] %>'
MEDIAFILES_LOCATION = 'folder_name_for_media_files_in_bucket'
DEFAULT_FILE_STORAGE = 'custom_storage.MediaS3Storage'
# If we're not using our S3 backend storage we need to serve the media files via path
if DEFAULT_FILE_STORAGE == "custom_storage.MediaS3Storage":
MEDIA_URL = 'https://%s.s3-website-us-east-1.amazonaws.com/%s/' % (MEDIAFILES_BUCKET, MEDIAFILES_LOCATION)
else:
MEDIA_URL = '/media/'
STATICFILES_BUCKET = '<%= #node["apps_data"]["aws"]["buckets"]["bucket-name"] %>'
STATICFILES_LOCATION = 'folder_name_for_static_files_in_bucket'
STATICFILES_STORAGE = '<%= #node["deploy_data"]["project_name"]["django_static_files_storage"] %>'
# If we're not using our S3 backend storage we need to serve the static files via path
if STATICFILES_STORAGE == "custom_storage.StaticS3Storage":
STATIC_URL = 'https://%s.s3-website-us-east-1.amazonaws.com/%s/' % (STATICFILES_BUCKET, STATICFILES_LOCATION)
else:
STATIC_URL = '/static/'
load static from staticfiles Django Template Tag
Change all uses of {% load static %} in templates to {% load static from staticfiles %}
The “static” from static files can make use of different back ends for files, including an S3 back end or local file back end. Using “load static” uses the Django template tags library which doesn’t handle different back ends.
Use this in the templates when including a static file and after including “static from staticfiles”:
{% static “path/to/the/file.ext” %}
This will figure out the full path to the file or if it’s in S3 it will insert a full URL to the file.
Example
<link rel="stylesheet" type="text/css" href="{% load static from staticfiles %}{% static "css/style.css" %}”>
Useful info
“django.contrib.staticfiles.storage.StaticFilesStorage” is the default Django static files backend
References
https://docs.djangoproject.com/en/1.9/howto/static-files/
https://www.caktusgroup.com/blog/2014/11/10/Using-Amazon-S3-to-store-your-Django-sites-static-and-media-files/

For nginx it works for me with the following configuration lines:
location /media {
alias /home/ubuntu/speedy-net/media; # Change to your own media directory here.
access_log off;
}
Also see my related question on Code Review.

You need to setup a server to serve static content on production. When only Debug is True, static content is served by Django. So you need to
1) Setup a server
2) Point server media path to STATIC_ROOT directory
3) Run collectstatic command of django to collect all the static files to STATIC_ROOT.
Please refer
https://docs.djangoproject.com/en/1.10/howto/static-files/

The following method worked for me:
I added the following configuration in Apache config file:
alias /media/ /path/to/media/
<Directory /alchemus/django/WebForm/media>
Require all granted
</Directory>
settings.py file contained the following settings for MEDIA:
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media/')
Make sure you have the following settings in urls.py:
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL,
document_root=settings.MEDIA_ROOT)
The above setting is to make sure that django server only serves media files during development, serving media files in production should be handled by Apache server.
References: https://docs.djangoproject.com/en/3.2/howto/deployment/wsgi/modwsgi/#serving-files

Just add this code in urls.py
urlpatterns = [
.........
.........
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
urlpatterns += static(settings.MEDIA_URL, document_root = settings.MEDIA_ROOT)

Related

heroku not serving css

I have the following code in my settings.py in django.
DEFAULT_FILE_STORAGE = 'hhhh.utils.MediaRootS3BotoStorage'
STATICFILES_STORAGE = 'hhhh.utils.StaticRootS3BotoStorage'
S3DIRECT_REGION = 'us-west-2'
S3_URL = '//%s.s3.amazonaws.com/' % AWS_STORAGE_BUCKET_NAME
MEDIA_URL = '//%s.s3.amazonaws.com/media/' % AWS_STORAGE_BUCKET_NAME
MEDIA_ROOT = MEDIA_URL
STATIC_URL = S3_URL + 'static/'
STATIC_ROOT = STATIC_URL + 'static_root/'
Heroku is not serving the ststic files. any ideas. I have the allowed hosts set to my site and heroku.
If I am reading your variables correctly, your static URL is built as so:
S3_URL + static + static_root
So, if your s3 bucket is named hhhh, then the final URL is
//hhhh.s3.amazonaws.com/static/static_root
Do files exist in that location?
For more info, Heroku offers a sample settings.py file regarding Django static files here: serving static assets with Django: https://devcenter.heroku.com/articles/django-assets
This page speaks specifically to hosting s3 files on s3 with heroku:
http://www.jorgechang.com/blog/howto-deploy-a-fault-tolerant-django-app-on-aws-part-2-moving-static-media-files-to-s3/
The author's STATIC_ROOT variable is blank, because static locations of files are set- and then the code later refers to the files on an Amazons3 location- it seems his code collects static files from a specific place and puts them in S3, then references them from there. You seem to be attempting to refer directly to an amazon s3 URL on your static_root var, so this laws gives you an alternate way to go it.

How to add my own files to django 'static' folder

I've read django static files document and made my django static files settings like this
setting.py
PROJECT_PATH = os.path.realpath(os.path.dirname(__file__))
STATIC_ROOT = os.path.join(PROJECT_PATH, 'static')
STATIC_URL = '/static/'
html page
<img src="{% static "admin/img/author.jpg" %}" alt="My image"/>
So if I address one of django default static files, it works fine. But if I add my own file and folders to the static folder, it doesn't show it.
I tried
python manage.py collectstatic
But nothing changed. How can I make it work?
A few things...
STATICFILES_DIRS = (
'path/to/files/in/development',
)
STATIC_ROOT = 'path/where/static/files/are/collected/in/production'
When DEBUG = True, Django will automatically serve files located in any directories within STATICFILES_DIRS when you use the {% static 'path/to/file' %} template tag.
When DEBUG = False, Django will not serve any files automatically, and you are expected to serve those files using Apache, Nginx, etc, from the location specified in STATIC_ROOT.
When you run $ manage.py collectstatic, Django will copy any and all files located in STATICFILES_DIRS and also files within any directory named 'static' in 3rd party apps, into the location specified by STATIC_ROOT.
I typically structure my project root as such:
my_project/
/static_assets/ (specified in STATICFILES_DIRS)
/js
/images
/static (specified in STATIC_ROOT)
I hope that helps you understand how the staticfiles app works.
STATIC_ROOT is where files are collected and moved to when collectstatic runs.
If you want files to be consolidated to there they should be found by the static file finder.
As an example, include the following in your settings
STATICFILES_FINDERS = ("django.contrib.staticfiles.finders.FileSystemFinder",
"django.contrib.staticfiles.finders.AppDirectoriesFinder")
now for one of the apps that are a part of your project, create a folder called static and put something in it.
When you run collectstatic you should see that file mentioned and it copied to your STATIC_ROOT
You can try adding
STATICFILES_DIRS = (
STATIC_PATH,
)
to your settings.py.
Also, if you haven't already, make sure to include
{% load static from staticfiles %}
in each of your templates where you wish to reference static files.
Lastly, make sure that the file you are referencing actually exists and the file path to it is correct.
Try to:
<img src="{{ STATIC_URL }}admin/img/author.jpg" alt="My image"/>
And in your view must be something like this:
...
from django.shortcuts import render_to_response
from django.conf import settings
def my_view(request):
...
static_url = getattr(settings, 'STATIC_URL')
...
return render_to_response(
template_name,
RequestContext(request, {
'STATIC_URL': static_url,
}))

Uploaded Image in django not working during production

During development my uploaded images are showing, but on production they are not.
Here are the codes:
#settings.py
STATIC_ROOT = '/home/eakdev/webapps/my_static'
MEDIA_ROOT = '/home/eakdev/webapps/my_static/media'
MEDIA_URL = '/media/'
#urls.py When I add this during development my images are showing correctly
urlpatterns += staticfiles_urlpatterns()
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
#base.html
<img class="img-responsive" src="{{ project.preview.url }}" alt="">
After reading some of the questions related to this, I think the reason why its not working is that my code is using dev server to serve the media files, which is only good for development. What do i change so that it would work in production?
The preferred way to serve media files in production is to set up your front-end webserver or CDN to serve them.
For example in nginx you'd include the following section in your server configuration:
location /media/ { # Should match MEDIA_URL
alias /path/to/mysite.com/media/; # Should match MEDIA_ROOT
}
And in Apache:
Alias /media/ /path/to/mysite.com/media/ # MEDIA_URL MEDIA_ROOT
<Directory /path/to/mysite.com/media> # MEDIA_ROOT
Require all granted
</Directory>
These would be the bare minimum directives and you can of course do a lot more with caching, access control, etc.
I had the same problem.
In settings.py i commented these lines:
#MEDIA_ROOT = '/home/prk/Documents/prakhar/mysite/media'
#MEDIA_URL = '/media/'
and added these lines:
MEDIA_ROOT = os.path.join(BASE_DIR, "..", "www", "media")
MEDIA_URL = '/media/'
When you will run server on localhost it will give error but in production it will work fine.
my project structure is:
/Wrapper/mysite/( ... and ... and manage.py and mysite and ...)
in wrapper directory i have a folder named www and inside it a folder named media.
Hope this helps.

Django 1.4 serving media files works, but not static

I am using Django 1.4 and for some reason i am able to serve media files, but not the static ones...
Here is my code:
settings:
MEDIA_ROOT = os.path.join(BASE_DIR, 'media/')
MEDIA_URL = '/media/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static/')
STATIC_URL = '/static/'
ADMIN_MEDIA_PREFIX = '/static/admin/'
urls.py:
(r'^media/(?P<path>.*)$', 'django.views.static.serve',{'document_root': settings.MEDIA_ROOT}),
(r'^static/(?P<path>.*)$', 'django.views.static.serve',{'document_root': settings.STATIC_ROOT}),
base.html:
<link href="{{ STATIC_URL }}css/bootstrap.css" rel="stylesheet">
<link href="{{ MEDIA_URL }}css/bootstrap-colorpicker.css" rel="stylesheet">
i get a 404 http not found... what am i doing wrong? An i did create the static folder in my project right next to media
http://mysite.com:8000/static/css/bootstrap.css
Your static folder should be under one app that you use it for.
For example, I have a project named my_project and an application named my_app, I have some static files used in my_app so I put them under ~/project_path/my_project/my_app/static
NB: my_app must be in INSTALLED_APPS. See STATICFILES_FINDERS documentation.
Edit:
As a best practice, you should have a global static folder in one app (the main one), for example a static folder how contains your html template basic resources as jquery, bootstrap, your global style.
And for the static files how's required only for one app, for example app foo, these files should be under foo/static folder
I suggest removing the explicit media and static views and allowing the staticfiles app to create them (when DEBUG is True under development).
Check the default finders are present in your settings.py
https://docs.djangoproject.com/en/1.4/ref/contrib/staticfiles/#std:setting-STATICFILES_FINDERS
Either add your project static directory to STATICFILES_DIRS (https://docs.djangoproject.com/en/1.4/ref/contrib/staticfiles/#std:setting-STATICFILES_DIRS) or place app specific static folders under each app. The app needs to be listed in the INSTALLED_APPS for the finders to locate the static content.
Do not place static files into STATIC_ROOT yourself. This directory is managed by the collectstatic command. See https://docs.djangoproject.com/en/dev/howto/static-files/#deployment
Here is how i define my media url in settings.py:
import os
ABSOLUTE_PATH = os.path.dirname(__file__)
MEDIA_ROOT = os.path.join(ABSOLUTE_PATH, '../media')
MEDIA_URL = '/media/'
STATIC_ROOT = os.path.join(ABSOLUTE_PATH, '../static')
STATIC_URL = "/static/"
So like you see the difference is ../media and ../static
Is mysite in your installed apps ? Django look inside your installed apps and check if there's a static folder there.

Django - serving user uploaded images

I am having some problems with serving user uploaded files from my Django application:
from models.py:
class Picture (models.Model):
title = models.CharField(max_length=48)
date_added = models.DateTimeField(auto_now=True)
content = models.ImageField(upload_to='pictures')
From the Django admin the files get uploaded to the user_res/pictures/ folder.
from the project's settings.py:
MEDIA_ROOT = 'user_res'
MEDIA_URL = '/user_res/'
STATIC_ROOT = ''
STATIC_URL = '/static/'
Every time I try to reference a static resource (namely css or js files), everything works fine using URLs such as
http://localhost:8000/static/<subfolder>/main.css.
However, I cannot access user uploaded files (which get created by the admin interface in the user_res/pictures folder with a relative URL such as
user_res/pictures/test.jpg
the URL is dynamically created with this line of code from a Django Picture model callable:
return '<img src="{}"/>'.format(self.content.url)
I have no dedicated url-s for either static or media files in the url.py file.
Does anybody have any idea as to how to make Django serve the media files? I understand that for live environments I will need to configure an http server to serve that particular directory, but for now I want to maintain a lightweight development suite.
Thank you.
Edit your urls.py file as shown below.
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = patterns('',
# ... the rest of your URLconf goes here ...
) + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
edit your projects settings.py to look like:
#Rest of the settings
MEDIA_URL = '/media/'
MEDIA_ROOT = 'media'
STATIC_ROOT = ''
STATIC_URL = '/static/'
Please read the official Django documentation about serving files uploaded by a user carefully. Link to docs: https://docs.djangoproject.com/en/1.5/howto/static-files/#serving-files-uploaded-by-a-user
I think the url attribute returns a relative URL ( Django's FileField documentation ), so you should have:
return '<img src="{}"/>'.format(MEDIA_URL + self.content.url)
Relative URLs won't work, as a user visiting "http://localhost/books/" would be requesting "http://localhost/books/user_res/pictures/test.jpg".

Categories