2010-04-21 15 views
6

Quindi voglio pubblicare un paio di mp3 da una cartella in /home/username/music. Non pensavo che sarebbe stato un grosso problema, ma sono un po 'confuso su come farlo usando le viste generiche e il mio URL.Django: pubblicazione di un download in una vista generica

urls.py

url(r'^song/(?P<song_id>\d+)/download/$', song_download, name='song_download'), 

L'esempio che sto seguendo si trova nella sezione di visualizzazione generica delle documentazioni Django: http://docs.djangoproject.com/en/dev/topics/generic-views/ (E 'tutto il senso in basso)

io non sono al 100 % sicuro su come adattare questo alle mie esigenze. Qui è il mio views.py

def song_download(request, song_id): 
    song = Song.objects.get(id=song_id) 

    response = object_detail(
     request, 
     object_id = song_id, 
     mimetype = "audio/mpeg", 
    ) 
    response['Content-Disposition'= "attachment; filename=%s - %s.mp3" % (song.artist, song.title) 

    return response 

Sono in realtà in perdita di come comunicare che voglio che sputare il mio mp3, invece di quello che fa ora che è quello di produrre un .mp3 con tutta la corrente pagine html contenute. Il mio modello dovrebbe essere il mio mp3? Devo impostare apache per servire i file o Django è in grado di recuperare l'mp3 dal filesystem (ovviamente i permessi necessari) e di servirlo? Se è necessario configurare Apache, come faccio a dirlo a Django?

Grazie in anticipo. Questi file sono tutti in HD, quindi non ho bisogno di "generare" nulla sul posto e mi piacerebbe evitare di rivelare la posizione di questi file, se possibile. Una semplice/canzone/1234/download sarebbe fantastica.

risposta

15

Perché vuoi farlo con una visualizzazione generica? E 'molto facile da fare questo senza viste generiche:

def song_download(request, song_id): 
    song = Song.objects.get(id=song_id) 
    fsock = open('/path/to/file.mp3', 'r') 
    response = HttpResponse(fsock, mimetype='audio/mpeg') 
    response['Content-Disposition'] = "attachment; filename=%s - %s.mp3" % \ 
            (song.artist, song.title) 
    return response 

non sono sicuro se è possibile fare questo lavoro in qualche modo con una vista generico. Ma in entrambi i casi, l'uso di uno è ridondante qui. Senza template per il rendering, il contesto che viene fornito automaticamente dalla vista generica è inutile.

+0

Beh dannazione, suppongo di essere così determinato a farlo funzionare con una visualizzazione generica, non ho pensato perché ne avevo bisogno. Esattamente quello di cui avevo bisogno, grazie! – TheLizardKing

+0

mp3 è file binari, quindi utilizzando la modalità di lettura file 'rb' invece di 'r' – iMath

+0

Ho cercato dappertutto per questo! Grazie per questo! – adbarads

2

Serving file statici con Django è una cattiva idea, utilizzare Apache, nginx ecc

http://docs.djangoproject.com/en/1.1/howto/static-files/

+0

Ti ho sentito, sono tutto per l'utilizzo di Apache, ma come posso ottenere la risposta accettata usando Apache come server web? Voglio utilizzare i miei propri URL e non rivelare il mio URL di download. – TheLizardKing

+0

Non sono un esperto di file-serving statico, ma scommetto che puoi riscrivere anche l'URL dei supporti statici –

+0

La mia contesa con il link precedente sono linee come "Ti consigliamo di utilizzare un server Web separato, ovvero uno che non è anche eseguendo Django - per servire i media. Ecco alcune buone scelte: "Li sento forte e chiaro ma diciamo che ho un percorso completo e/o un url per il file, come posso spitarlo usando il mio URL sopra menzionato? messa in piega? Sto cercando di trovare progetti open source di Django per vedere come lo fanno. – TheLizardKing

5

Per concludere il mio commento di Tomasz Zielinski in una vera risposta:

Per diversi motivi è davvero meglio lasciare che apache/nginx/etc faccia il lavoro di invio dei file. La maggior parte dei server ha meccanismi per aiutare in quel caso: Apache e lighttpd hanno xsendfile, nginx ha X-Accel-Redirect.

L'idea è che è possibile utilizzare tutte le funzionalità di django come nice url, metodi di autenticazione, ecc, ma lasciare che il server faccia il lavoro di servire i file. Ciò che la tua vista di django deve fare è restituire una risposta con un'intestazione speciale. Il server sostituirà quindi la risposta con il file effettivo.

Esempio per apache:

def song_download(request): 
    path = '/path/to/file.mp3' 
    response = HttpResponse() 
    response['X-Sendfile'] = smart_str(path) 
    response['Content-Type'] = "audio/mpeg" 
    response['Content-Length'] = os.stat(path).st_size 
    return response 
  • installare mode_xsendfile
  • aggiungere XSendFileOn on e (a seconda della versione) XSendFileAllowAbove on o XSendFilePath the/path/to/serve/from per la configurazione di Apache.

In questo modo non si rivaluta il percorso del file e si conserva tutta la gestione degli URL in django.

+0

potresti usare os.path.getsize (pathToFile) invece di os.stat (path) .st_size – iMath

Problemi correlati