Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to serve media files on Django production environment?

Tags:

python

django

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?

like image 621
H.G. Avatar asked Aug 20 '16 06:08

H.G.


People also ask

How do I serve media files in Django?

To make Django development server serve static we have to add a URL pattern in sitewide urls.py file. Now visit http://127.0.0.1:8000/media/python.png again, this time you should be able to see the image. Just as with static files, in the production, you should always use a real web server to serve media files.

Where are Django media files stored?

By default, Django stores files locally, using the MEDIA_ROOT and MEDIA_URL settings. The examples below assume that you're using these defaults. However, Django provides ways to write custom file storage systems that allow you to completely customize where and how Django stores files.

What is static and media files in Django?

First off, you'll typically find these three types of files in a Django project: Source code: These are your core Python modules and HTML files that make up every Django project, where you define your models, views, and templates. Static files: These are your CSS stylesheets, JavaScript files, fonts, and images.


3 Answers

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

like image 154
Aswin Kumar K P Avatar answered Oct 24 '22 08:10

Aswin Kumar K P


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.

like image 24
Afnan Nazir Avatar answered Oct 24 '22 07:10

Afnan Nazir


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/

like image 3
Ehsaan Israr Avatar answered Oct 24 '22 08:10

Ehsaan Israr