##### Nginx ##### If you serve Django behind Nginx, then you can delegate the file download service to Nginx and get increased performance: * lower resources used by Python/Django workers ; * faster download. See `Nginx X-accel documentation`_ for details. **************************** Configure some download view **************************** As an example, let's consider an application called "myapp". :file:`settings.py`: .. code-block:: python INSTALLED_APPS = ( # ... 'myapp', # ... ) MYAPP_STORAGE_LOCATION = '/var/www/files/' # Could be MEDIA_ROOT for public # files. This application holds a ``Document`` model. :file:`myapp/models.py`: .. code-block:: python from django.conf import settings from django.core.files.storage import FileSystemStorage from django.db import models storage = FileSystemStorage(location=settings.MYAPP_STORAGE_LOCATION) class Document(models.Model): file = models.FileField(storage=storage, upload_to='document') Notice the ``storage`` and ``upload_to`` parameters: files for ``Document`` model live in :file:`/var/www/files/document/` folder. Then we configured a download view for this model, restricted to authenticated users: :file:`myapp/urls.py`: .. code-block:: python from django.conf.urls import url, url_patterns from django.contrib.auth.decorators import login_required from django_downloadview import ObjectDownloadView from myapp.models import Document download = login_required(ObjectDownloadView.as_view(model=Document)) url_patterns = ('', url('^document/(?P[0-9]+/download/$', download, name='download'), ) As is, Django is to serve the files, i.e. load chunks into memory and stream them. Nginx is much more efficient for the actual streaming... Let's use it! *************** Configure Nginx *************** See `Nginx X-accel documentation`_ for details. Here is what you could have in :file:`/etc/nginx/sites-available/default`: .. code-block:: nginx charset utf-8; # Django-powered service. upstream frontend { server 127.0.0.1:8000 fail_timeout=0; } server { listen 80 default; # File-download proxy. # # Will serve /var/www/files/myfile.tar.gz when passed URI # like /optimized-download/myfile.tar.gz # # See http://wiki.nginx.org/X-accel # and https://github.com/benoitbryon/django-downloadview location /optimized-download { internal; # Location to files on disk. # See Django's settings.NGINX_DOWNLOAD_MIDDLEWARE_MEDIA_ROOT alias /var/www/files/; } # Proxy to Django-powered frontend. location / { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_redirect off; proxy_pass http://frontend; } } ... where specific configuration is the ``location /optimized-download`` section. .. note:: ``/optimized-download`` is not available for the client, i.e. users won't be able to download files via ``/optimized-download/``. .. warning:: Make sure Nginx can read the files to download! Check permissions. ************************************************ Global delegation, with XAccelRedirectMiddleware ************************************************ If you want to delegate all file downloads to Nginx, then use :py:class:`django_downloadview.nginx.XAccelRedirectMiddleware`. Register it in your settings: .. code-block:: python MIDDLEWARE_CLASSES = ( # ... 'django_downloadview.nginx.XAccelRedirectMiddleware', # ... ) Setup the middleware: .. code-block:: python NGINX_DOWNLOAD_MIDDLEWARE_MEDIA_ROOT = MYAPP_STORAGE_LOCATION NGINX_DOWNLOAD_MIDDLEWARE_MEDIA_URL = '/optimized-download' Optionally fine-tune the middleware. Default values are ``None``, which means "use Nginx's defaults". .. code-block:: python NGINX_DOWNLOAD_MIDDLEWARE_EXPIRES = False # Force no expiration. NGINX_DOWNLOAD_MIDDLEWARE_WITH_BUFFERING = False # Force buffering off. NGINX_DOWNLOAD_MIDDLEWARE_LIMIT_RATE = False # Force limit rate off. ************************************************* Local delegation, with x_accel_redirect decorator ************************************************* If you want to delegate file downloads to Nginx on a per-view basis, then use :py:func:`django_downloadview.nginx.x_accel_redirect` decorator. Adapt :file:`myapp/urls.py`: .. code-block:: diff from django.conf.urls import url, url_patterns from django.contrib.auth.decorators import login_required from django_downloadview import ObjectDownloadView + from django_downloadview.nginx import x_accel_redirect from myapp.models import Document download = login_required(ObjectDownloadView.as_view(model=Document)) + download = x_accel_redirect(download, + media_root=settings.MY_APP_STORAGE_LOCATION, + media_url='/optimized-download') url_patterns = ('', url('^document/(?P[0-9]+/download/$', download, name='download'), ) ************* Common issues ************* ``Unknown charset "utf-8" to override`` ======================================= Add ``charset utf-8;`` in your nginx configuration file. ``open() "path/to/something" failed (2: No such file or directory)`` ==================================================================== Check your ``settings.NGINX_DOWNLOAD_MIDDLEWARE_MEDIA_ROOT`` in Django configuration VS ``alias`` in nginx configuration: in a standard configuration, they should be equal. ********** References ********** .. target-notes:: .. _`Nginx X-accel documentation`: http://wiki.nginx.org/X-accel