14đź‘Ť
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
8đź‘Ť
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.
- [Django]-How to get getting base_url in django template
- [Django]-Itertools.groupby in a django template
- [Django]-Django-rest-framework returning 403 response on POST, PUT, DELETE despite AllowAny permissions
3đź‘Ť
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/
- [Django]-Django :How to integrate Django Rest framework in an existing application?
- [Django]-Detect mobile, tablet or Desktop on Django
- [Django]-A field with precision 10, scale 2 must round to an absolute value less than 10^8
3đź‘Ť
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.
- [Django]-How do you detect a new instance of the model in Django's model.save()
- [Django]-Django-rest-framework returning 403 response on POST, PUT, DELETE despite AllowAny permissions
- [Django]-Get the list of checkbox post in django views
1đź‘Ť
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
- [Django]-Django models: mutual references between two classes and impossibility to use forward declaration in python
- [Django]-How to produce a 303 Http Response in Django?
- [Django]-Removing 'Sites' from Django admin page
1đź‘Ť
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
- [Django]-How do I match the question mark character in a Django URL?
- [Django]-Django 2 – How to register a user using email confirmation and CBVs?
- [Django]-Django Multiple Authentication Backend for one project
1đź‘Ť
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)
- [Django]-PHP Frameworks (CodeIgniter, Yii, CakePHP) vs. Django
- [Django]-__init__() got an unexpected keyword argument 'mimetype'
- [Django]-Django-Forms with json fields
1đź‘Ť
I had the same error but the logic is that django serves media files when it’s in production mode. That means when debug
is True
but when debug
is set to False
means in production mode you will need to specify the media URL too in your 1urls_pattern`.
I got it fixed with:
# import serve and repath
from django.views.static import serve
from django.urls import path, include,re_path
and then added:
re_path(r'^media/(?P<path>.*)$',serve,{'document_root':settings.MEDIA_ROOT}),
to my urls_patterns
.
- [Django]-How to make an auto-filled and auto-incrementing field in django admin
- [Django]-Substring in a django template?
- [Django]-Images from ImageField in Django don't load in template