As vezes você tem uma aplicação que precisa servir arquivos estáticos protegidos (entende-se arquivos estáticos que apenas alguns usuários deveriam ter acesso). Abaixo irei mostrar um snippet para nginx e django, com o qual é possível fazer a verificação da requisição do arquivo protegido com django e deixar o nginx servir o arquivo.

O apache utiliza o xsendfile que é bem semelhante ao X-Accel-Redirect do nginx, com a diferença que o apache deseja que você informe o caminho completo do arquivo e o nginx o caminho relativo a pasta que você irá definir que contém os arquivos protegidos.

Crie um modulo python e armazene o seguinte script (estou supondo que você tem uma settings chamada PROJECT_ROOT que contém o caminho root do projeto, você deve colocar a variável settings USE_XACCELREDIRECT=True no ambiente de produção e False no ambiente de desenvolvimento) 

# -*- coding: utf-8 -*-

import os

from django.core.files.storage import FileSystemStorage
from django.conf import settings
from django.views.static import serve
from django.http import HttpResponse
from django.utils.encoding import smart_str

SECURE_STORAGE = FileSystemStorage(location=settings.PROJECT_ROOT, base_url='/')

USE_XACCELREDIRECT = getattr(settings, 'USE_XACCELREDIRECT', False)

def xaccelredirect(request, path, document_root=settings.PROJECT_ROOT):
    split = path.split('/')
    filename = split[-1]
    filename = filename.replace(" ", '_')
    if USE_XACCELREDIRECT:
        #fullpath = smart_str(os.path.join(document_root, path))
        # This is where the magic takes place.
        response = HttpResponse()
        if not path.startswith('/'):
            path = "/" + path
        response['X-Accel-Redirect'] = path
        # Unset the Content-Type as to allow for the webserver
        # to determine it.
        response['Content-Type'] = ''
        response['Content-Disposition'] = 'attachment; filename=%s' % smart_str(filename)
        return response
    response = serve(request, path, document_root)
    response['Content-Disposition'] = 'attachment; filename=%s' % smart_str(filename)
    return response

 

Na sua view você deve importar esta função e utilizar ela como resposta da sua view.

Por Exemplo: você cria uma pasta chamada protected dentro do diretório ROOT do projeto e supondo que você quer enviar um arquivo protegido chamado imagem.png, que está dentro desta pasta, você chama a função acima criada passando como parâmetros o objeto request e o caminho "protected/imagem.png".

def minha_view(request):
    # minha verificação se o usuário pode acessar o arquivo
    return xaccelredirect(request, "protected/imagem.png")

 

Nas configurações do nginx é preciso que você insira essa linha dentro das configurações do seu site

location /protected/ {
    internal;
    root /caminho/root/do/projeto/;
}

 

Bem é isso ai.