2010-04-21 15 views
6

Así que quiero servir un par de mp3 de una carpeta en /home/username/music. No pensé que esto sería tan importante, pero estoy un poco confundido sobre cómo hacerlo usando vistas genéricas y mi propia URL.Django: sirviendo una descarga en una vista genérica

urls.py

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

El ejemplo que estoy siguiendo se encuentra en la sección de visión genérica de las documentaciones de Django: http://docs.djangoproject.com/en/dev/topics/generic-views/ (Es todo el camino en la parte inferior)

no estoy 100 % seguro de cómo adaptar esto a mis necesidades. Aquí está mi 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 

De hecho, estoy en una pérdida de cómo transmitir que yo quiero que escupir mi mp3 en lugar de lo que lo hace ahora que es dar salida a una .mp3 con toda la corriente páginas html contenidas ¿Debería mi plantilla ser mi mp3? ¿Debo configurar Apache para que sirva los archivos o Django puede recuperar el mp3 del sistema de archivos (permisos adecuados, por supuesto) y publicarlo? Si necesita configurar Apache, ¿cómo se lo digo a Django?

Gracias de antemano. Todos estos archivos están en HD, así que no necesito "generar" nada en el lugar y me gustaría evitar que se revele la ubicación de estos archivos si es posible. Un simple/canción/1234/descarga sería fantástico.

Respuesta

15

¿Por qué quieres hacer esto con una vista genérica? Es muy fácil de hacer esto sin vistas genéricas:

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 

No estoy seguro de si es posible hacer este trabajo de alguna manera con una vista genérica. Pero de cualquier manera, usar uno es redundante aquí. Sin una plantilla para representar, el contexto que proporciona automáticamente la vista genérica es inútil.

+0

Bueno, maldición, supongo que me obsesioné en hacer que funcione con una vista genérica. No pensé por qué siquiera la necesitaba. Exactamente lo que necesitaba, ¡gracias! – TheLizardKing

+0

mp3 son archivos binarios, así que usando el modo de lectura de archivo 'rb' en lugar de 'r' – iMath

+0

¡Busqué todo esto! ¡Gracias por esto! – adbarads

2

servir archivos estáticos con Django es una mala idea, el uso de Apache, Nginx etc.

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

+0

Te escucho, estoy a favor de usar apache, pero ¿cómo puedo lograr la respuesta aceptada usando Apache como mi servidor web? Quiero usar mis propias URL y no revelar mi url de descarga. – TheLizardKing

+0

No soy un experto en archivos estáticos, pero apuesto a que también puede reescribir la URL estática de medios –

+0

Mi argumento con el enlace anterior son líneas como "Recomendamos usar un servidor web separado, es decir, uno que no sea también ejecutando Django - para servir multimedia. Aquí hay algunas buenas opciones: "Los escucho alto y claro, pero digamos que tengo una ruta completa y/o una url en el archivo, ¿cómo escupo eso usando mi URL mencionada anteriormente? ¿estilo? Estoy tratando de encontrar proyectos open source django para ver cómo lo hacen. – TheLizardKing

5

Para terminar mi comentario a Tomasz Zielinski en una respuesta real:

Por varias razones es de hecho es mejor dejar que apache/nginx/etc haga el trabajo de enviar archivos. La mayoría de los servidores tienen mecanismos para ayudar en ese uso: Apache y lighttpd tienen xsendfile, nginx tiene X-Accel-Redirect.

La idea es que puedes usar todas las características de django como buenas URL, métodos de autenticación, etc., pero deja que el servidor haga el trabajo de servir archivos. Lo que tu vista django tiene que hacer es devolver una respuesta con un encabezado especial. El servidor reemplazará la respuesta con el archivo real.

Ejemplo de 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 
  • instalación mode_xsendfile
  • añadir XSendFileOn on y (dependiendo de la versión) o XSendFileAllowAbove onXSendFilePath the/path/to/serve/from a su configuración de Apache.

De esta forma no revelas la ubicación del archivo y conservas toda la administración de url en django.

+0

puede usar os.path.getsize (pathToFile) en lugar de os.stat (ruta) .st_size – iMath

Cuestiones relacionadas