- Install from PyPI with pip:
pip install django-privates
- Add the app to your
INSTALLED_APPS
for admin integration:
INSTALLED_APPS = [
...
"privates",
...
]
You need to set the following settings:
PRIVATE_MEDIA_ROOT
: private equivalent ofMEDIA_ROOT
- the base location where private media files will be stored.PRIVATE_MEDIA_URL
: private equivalent ofMEDIA_URL
. Note that your webserver must be configured appropriately for this, see the sendfile documentation. Your webserver may not directly serve these URLs, otherwise files can be downloaded without authentication.SENDFILE_BACKEND
: depends on your webserver, see the sendfile documentation.SENDFILE_ROOT
: should be set toPRIVATE_MEDIA_ROOT
.SENDFILE_URL
: should be set toPRIVATE_MEDIA_URL
.
No URLs need to be configured. However, for development, you likely want to serve the private media file uploads with Django. This can be achieved via settings:
SENDFILE_BACKEND = "django_sendfile.backends.development"
The simplest way is to use the model field, which is a drop-in replacement of Django's django.db.models.FileField
.
from django.db import models
from privates.fields import PrivateMediaFileField, PrivateMediaImageField
class IDDocument(models.Model):
pdf = PrivateMediaFileField(blank=True)
mugshot = PrivateMediaImageField(upload_to="mugshots/%Y/")
This uses the underlying privates.storages.private_media_storage
.
There is built in admin integration via a mixin. This takes care of replacing the default widget so you can open the private media files, and perform permission checks.
from django.contrib import admin
from privates.admin import PrivateMediaMixin
from .models import Invoice
@admin.register(Invoice)
class InvoiceAdmin(PrivateMediaMixin, admin.ModelAdmin):
pass
By default, this mixin requires you to have the <applabel>.can_change_<model>
permission.
Attributes:
privates.admin.PrivateMediaMixin.private_media_permission_required
: (custom) permission to check instead of the default<applabel>.can_change_<model>
privates.admin.PrivateMediaMixin.private_media_view_options
: optional arguments to forward to thesendfile.sendfile
function.
The private media files still need to be served to authorized users. The process for this is roughly:
Define a view, which:
- Checks the user permissions
- Looks up the requested model instance
- Look up the relevant file field of the model
- Extract the path on-disk of the file
- Return a response which contains the file path information in a format the webserver understands
- Let the webserver (nginx, apache...) serve the file as efficiently as possible
- Hook up the view to a URL in your
urls.py
- Expose the download button with a simple anchor tag URL or button action in your template(s)
Django Privates ships with a built in permission-check view, used by the admin integration. You are encouraged to re-use this.
It's built on top of django.contrib.auth.mixins.PermissionRequiredMixin
and django.views.generic.DetailView
, so the methods/attributes of these base classes are available.
from privates.views import PrivateMediaView
class InvoicePDFView(PrivateMediaView):
queryset = Invoice.objects.all()
file_field = "pdf"
permission_required = "applabel.can_change_invoice"
You can also easily serve file contents in regular views and/or djangorestframework endpoints, for example:
from django_sendfile import sendfile
from rest_framework import permissions
from rest_framework.generics import GenericAPIView
class DownloadFileView(GenericAPIView):
queryset = IDDocument.objects.all()
permission_classes = (permissions.IsAuthenticated,)
def get(self, request, *args, **kwargs):
instance = self.get_object() # the get_object methods performs permission checks
filepath = instance.pdf.path
return sendfile(request, path)
To isolate tests, you should clean up any uploaded files generated during tests. There is a wrapper around django.test.override_settings
available to facilitate this:
from privates.test import temp_private_root
@temp_private_root()
class MyTests(TestCase):
pass
The usage is the same as override_settings
, so you can use it as a class decorator, test method decorator or context manager.