Django Protected Media
Django Protected Media is a Django app that manages media that are considered sensitive in a protected fashion.
Not only does the media get stored in a separate filesystem location, but authorisation is also required to access it.
The application allows for setups where Django performs the authorisation, but hands off the serving of the file to a web server, like Nginx.
Quick start
- Add "protected_media" to your INSTALLED_APPS setting like this:
INSTALLED_APPS = [
...
'protected_media.apps.ProtectedMediaConfig',
]
- Include the URLconf in your project urls.py like this::
path('protected/', include('protected_media.urls')),
- Add the following settings to
settings.py
if the defaults need to be tweaked:
PROTECTED_MEDIA_ROOT = "%s/protected/" % BASE_DIR
PROTECTED_MEDIA_URL = "/protected"
PROTECTED_MEDIA_SERVER = "nginx" # Defaults to "django"
PROTECTED_MEDIA_LOCATION_PREFIX = "/internal" # Prefix used in nginx config
PROTECTED_MEDIA_AS_DOWNLOADS = False # Controls inclusion of a Content-Disposition header
- Use the new field classes in your models:
from protected_media.models import ProtectedImageField, ProtectedFileField
def SomeModel(models.Model):
document = ProtectedFileField(upload_to="uploads/")
picture = ProtectedImageField(upload_to="uploads/")
# Files will be stored under PROTECTED_MEDIA_ROOT + upload_to
Overview
Django manages media based on the following definitions:
BASE_DIR = "/some/application/dir/"
MEDIA_ROOT = "%s/media/" % BASE_DIR
MEDIA_URL = "/media/"
File- and image fields are typically defined as:
document = models.FileField(upload_to="uploads/")
picture = models.ImageField(upload_to="uploads/")
# Files will be stored under MEDIA_ROOT + upload_to
In a typical production environment one would let nginx
(or some other server) serve the media:
# Publicly accessible media
location ^~ /media/ {
alias /some/application/dir/media
}
This works well when the media should be publically accessible. However, if the media should be protected, we need a way for Django to check whether the request for the media should only be allowed for logged in (or more stringent criteria) users.
protected_media
application
The The protected_media
application consists of
- new
settings.py
attributes, - a customized FileSystemStorage class,
- a custom handler for the protected media URL and
- additional web server configuration if serving via
nginx
or something similar.
Protected media is stored in a different physical location to publically accessible media. The following settings can be specified in settings.py
:
PROTECTED_MEDIA_ROOT = "/some/application/dir/protected/"
PROTECTED_MEDIA_URL = "/protected"
PROTECTED_MEDIA_SERVER = "nginx" # Defaults to "django"
PROTECTED_MEDIA_LOCATION_PREFIX = "/internal" # Prefix used in nginx config
When defining a file or image field that needs to be protected, we use one of the classes provided by the protected_media
application:
ProtectedFileField
ProtectedImageField
Protected file- and image fields are typically defined as:
document = ProtectedFileField(upload_to="uploads/")
picture = ProtectedImageField(upload_to="uploads/")
# Files will be stored under PROTECTED_MEDIA_ROOT + upload_to
These classes have a custom storage backend ProtectedFileSystemStorage
which mananges the filesystem location and URLs associated with protected media.
When nginx
is used, the configuration must be updated to look like this:
# Publicly accessible media
location /media {
alias /some/application/dir/media;
}
# Protected media
location /internal {
internal;
alias /some/application/dir/protected;
}