2010-02-19 8 views
10

Ho bisogno di restituire file css e file js secondo logica specifica. Chiaramente, il servizio statico non esegue ciò di cui ho bisogno. Ho una vista, il cui metodo di rendering usa la logica per trovare il file corretto, ma poi devo restituirlo. Tecnicamente, posso solo leggere il file e inserirlo in un oggetto HttpResponse con il tipo mime appropriato, ma mi chiedevo se esistesse una strategia migliore. (come fpassthru() in php)Come restituire i file statici che passano attraverso una vista in django?

+1

Quale non sta eseguendo quello che ti serve, file statici server web serving, o 'django.views.static.serve'? –

+0

nessuno dei due :) –

+0

in realtà, la domanda di grammatica. è "nessuno di" o "entrambi"? –

risposta

-1

Dovrebbe essere uno spreco usare django per servire contenuti statici (per non parlare di diversi ordini di grandezza più lenti).

Preferisco convertire la vista in un processore di contesto e utilizzare le variabili nei modelli per trovare quali blocchi includere.

+0

sia esattamente ciò di cui voglio allontanarmi. Sto già includendo le cose, con il risultato che i file css e js sono inclusi nel file html, impedendo qualsiasi forma di memorizzazione nella cache (poiché si ritiene che la pagina nel suo complesso cambi). Voglio essere in grado di spedire js e css, ma dal momento che questa spedizione dipende dai plugin della mia applicazione che sono disponibili, ho bisogno di eseguire una certa logica prima di spedire il file. –

+0

Intendi prevenire qualsiasi forma di memorizzazione nella cache di Django? Poiché avere css e js include l'hardcoded nel modello, non impedirà al browser dell'utente di memorizzarli nella cache. Non sono chiaro su quale sia il vero problema. Sembra che tu abbia problemi a memorizzare l'intera pagina a causa degli include dinamici. Perché non memorizzare nella cache il resto della pagina e lasciare che il browser/il tuo server web faccia il resto (che è comunque il suo lavoro)? – Tom

+0

Questo sarebbe un grande commento o un avvertimento dopo una risposta reale. –

1

Passare un iteratore (ad esempio il risultato di open()) al costruttore HttpResponse.

1

Perché non restituire un HttpResponseRedirect nel percorso del file statico corretto?

+2

perché il file non è direttamente accessibile. –

8

Quale software di server Web stai usando?

Almeno per Apache e NginX, esiste un modulo che consente di utilizzare l'intestazione HTTP X-SendFile. Il sito Web di NginX dice che anche Lighty può farlo.

Secondo lei involucro:

... 

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 

quindi è possibile collegare la vista via http://mysite.com/url_path/to/serve_hidden_css_file/.

Puoi utilizzarlo ogni volta che devi fare qualcosa su un file richiesto che non dovrebbe essere direttamente accessibile agli utenti, come limitare chi può accedervi o contare le richieste ad esso per statistiche, o altro.

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

16

Questo è quello che ho usato:

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

Avevo bisogno della modalità 'rb' sulla funzione open(), o questo codice incasinato i miei pdf. Corrisponde al codice utilizzato in django/views/static.py. –

+2

Mi sembra che questo faccia caricare l'intero file in memoria. Non è vero? –

+0

@EmanuelePaolini: puoi passare un iteratore a 'HttpResponse', invece, ho modificato la risposta per riflettere questo. – Flimm

4

Perché non utilizzare Django staticfiles all'interno della vostra vista

from django.contrib.staticfiles.views import serve 

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

Le [Documenti] (https://docs.djangoproject.com/en/1.4/ref/contrib/staticfiles/#other-helpers) dicono:. "Attenzione Questo punto di vista funziona solo se DEBUG è True. Ciò è dovuto al fatto che questa visualizzazione è gravemente inefficiente e probabilmente non sicura, ma è destinata esclusivamente allo sviluppo locale e non dovrebbe mai essere utilizzata nella produzione. " –

1

Serving i file direttamente da una vista sono molto lenti. Se stai cercando un file normale, vedi questa domanda: Having Django serve downloadable files

Per semplificare la visualizzazione dei file tramite una vista (ad esempio per scopi di debug) continua a leggere.

# 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) 

Questo permette di scaricare il file da: http://127.0.0.1:8080/app/test-files/myxml/

Problemi correlati