2010-02-19 12 views
10

Necesito devolver archivos css y js de acuerdo con la lógica específica. Claramente, el servicio estático no ofrece lo que necesito. Tengo una vista, cuyo método de render usa la lógica para encontrar el archivo correcto, pero luego tengo que devolverlo. Técnicamente, puedo leer el archivo y rellenarlo en un objeto HttpResponse con el tipo de mime adecuado, pero me preguntaba si había una mejor estrategia. (como fpassthru() en php)Cómo devolver archivos estáticos que pasan por una vista en django?

+1

la que no se está llevando a cabo lo que necesita, archivo estático servidor web que sirve, o 'django.views.static.serve'? –

+0

ninguna de las dos :) –

+0

en realidad, pregunta de gramática. ¿es "ninguno de" o "ambos"? –

Respuesta

-1

Debería ser un desperdicio usar django para servir contenido estático (sin mencionar que varios órdenes de magnitud son más lentos).

Prefiero convertir la vista en un procesador de contexto y usar las variables en las plantillas para encontrar qué bloques incluir.

+0

es exactamente de lo que quiero alejarme. Ya estoy incluyendo las cosas, con el resultado de que los archivos css y js se incluyen codificados en el archivo html, lo que impide cualquier forma de almacenamiento en caché (ya que se considera que la página en su totalidad cambia). Deseo poder enviar js y css, pero dado que este envío depende de los complementos de mi aplicación que estén disponibles, necesito realizar un poco de lógica antes de enviar el archivo. –

+0

¿Quiere decir que impide cualquier forma de almacenamiento en caché de Django? Debido a que tener css & js incluye código fijo en la plantilla no impedirá que el navegador del usuario los guarde en caché. No tengo claro cuál es el problema real. Parece que está teniendo problemas para almacenar en caché toda la página debido a las inclusiones dinámicas. ¿Por qué no almacenar en caché el resto de la página y dejar que el navegador/su servidor web haga el resto (que de todos modos es su trabajo)? – Tom

+0

Esto sería un gran comentario o una advertencia después de una respuesta real. –

1

Pase un iterador (como el resultado de open()) al constructor HttpResponse.

1

¿Por qué no devuelve un HttpResponseRedirect a la ubicación del archivo estático correcto?

+2

porque no se puede acceder directamente al archivo. –

8

¿Qué software de servidor web está utilizando?

Al menos para Apache y NginX, hay un módulo que le permite usar el encabezado HTTP X-SendFile. El sitio web de NginX dice que Lighty puede hacer esto también.

En su opinión envoltorio:

... 

abspath = '/most_secret_directory_on_the_whole_filesystem/protected_filename.css' 

response = HttpResponse() 
response['X-Sendfile'] = abspath 

response['Content-Type'] = 'mimetype/submimetype' 
# or let your webserver auto-inject such a header field 
# after auto-recognition of mimetype based on filename extension 

response['Content-Length'] = <filesize> 
# can probably be left out if you don't want to hassle with getting it off disk. 
# oh, and: 
# if the file is stored via a models.FileField, you just need myfilefield.size 

response['Content-Disposition'] = 'attachment; filename=%s.css' \ 
    % 'whatever_public_filename_you_need_it_to_be' 

return response 

Entonces se puede conectar a través de la vista http://mysite.com/url_path/to/serve_hidden_css_file/.

Puede usarlo en cualquier momento que necesite hacer algo en un archivo solicitado que no debe ser accesible directamente para los usuarios, como limitar quién puede acceder a él o contar solicitudes de estadísticas o lo que sea.

Para Apache: http://tn123.ath.cx/mod_xsendfile/
Para Nginx: http://wiki.nginx.org/NginxXSendfile

16

Esto es lo que he utilizado:

test_file = open('/home/poop/serve/test.pdf', 'rb') 
response = HttpResponse(content=test_file) 
response['Content-Type'] = 'application/pdf' 
response['Content-Disposition'] = 'attachment; filename="%s.pdf"' \ 
            % 'whatever' 
return response 
+0

Necesitaba el modo 'rb' en la función open(), o este código ha estropeado mis pdfs. Esto coincide con el código utilizado en django/views/static.py. –

+2

Me parece que esto hace que todo el archivo se cargue en la memoria. ¿No es así? –

+0

@EmanuelePaolini: puede pasar un iterador a 'HttpResponse' en su lugar, he modificado la respuesta para reflejar esto. Los documentos – Flimm

4

¿Por qué no usar Django staticfiles dentro de la vista

from django.contrib.staticfiles.views import serve 

... 
def view_function(request): 
    return serve(request, 'absolute_path_to_file_name') 
+7

[] (https://docs.djangoproject.com/en/1.4/ref/contrib/staticfiles/#other-helpers) dicen:. "Advertencia Este punto de vista sólo funcionará si DEBUG es True. Esto se debe a que esta vista es extremadamente ineficiente y probablemente insegura. Esto solo está destinado al desarrollo local y nunca debe utilizarse en la producción ". –

1

Sirviendo archivos directamente desde una vista es muy lento. Si está buscando una entrega normal de archivos, consulte esta pregunta: Having Django serve downloadable files

Para servir archivos con una vista muy sencilla (para fines de depuración, por ejemplo) siga leyendo.

# In your urls.py: 
url(r'^test-files/(?P<name>.+)/$', views.test_files, name='test_files'), 

# In your views.py: 
from django.http.response import HttpResponse 
from django.views.decorators.csrf import csrf_exempt 

@csrf_exempt # (Allows file download with POST requests, can be omitted) 
def test_files(request, name): 
    if name == "myxml": 
     fsock = open("/djangopath/data/static/files/my.xml", "rb") 
     return HttpResponse(fsock) 

Esto le permite descargar el archivo desde: http://127.0.0.1:8080/app/test-files/myxml/

Cuestiones relacionadas