Джанго: обслуживание загрузки в общем виде - PullRequest
7 голосов
/ 21 апреля 2010

Итак, я хочу подать пару mp3-файлов из папки в /home/username/music. Я не думал, что это будет так важно, но я немного запутался, как это сделать, используя общие представления и мой собственный URL.

urls.py

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

Пример, которому я следую, находится в разделе общего вида документации Django: http://docs.djangoproject.com/en/dev/topics/generic-views/ (все внизу)

Я не уверен на 100% в том, как приспособить это к моим потребностям. Вот мой 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

На самом деле я не знаю, как передать, что я хочу, чтобы он выплевывал мой mp3 вместо того, что он делает сейчас - вывод .mp3 со всеми текущими страницами, содержащими html. Должен ли мой шаблон быть моим mp3? Нужно ли настраивать apache для обслуживания файлов, или Django может извлекать mp3 из файловой системы (конечно, соответствующие разрешения) и обслуживать это? Если нужно настроить Apache, как мне сообщить об этом Django?

Заранее спасибо. Все эти файлы находятся на жестком диске, поэтому мне не нужно «генерировать» что-либо на месте, и я бы хотел предотвратить раскрытие местоположения этих файлов, если это возможно. Простая / песня / 1234 / была бы фантастической.

Ответы [ 3 ]

15 голосов
/ 21 апреля 2010

Почему вы хотите сделать это с общим видом? Это очень легко сделать без общих представлений:

from django.http import HttpResponse


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

Я не уверен, возможно ли как-то заставить эту работу работать с общим видом. Но в любом случае, использование одного излишне здесь. Без отображаемого шаблона контекст, автоматически предоставляемый общим представлением, бесполезен.

7 голосов
/ 05 сентября 2011

Чтобы превратить мой комментарий к Томашу Зелински в настоящий ответ:

По нескольким причинам действительно лучше, чтобы apache / nginx / etc выполнял отправку файлов. Большинство серверов имеют механизмы, помогающие в этом случае использования: Apache и lighttpd имеют xsendfile, nginx имеет X-Accel-Redirect.

Идея состоит в том, что вы можете использовать все функции django, такие как красивые URL, методы аутентификации и т. Д., Но позволить серверу выполнять работу по обслуживанию файлов. Ваше представление django должно возвращать ответ со специальным заголовком. Затем сервер заменит ответ фактическим файлом.

Пример для 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
  • установить mode_xsendfile
  • добавьте XSendFileOn on и (в зависимости от версии) XSendFileAllowAbove on или XSendFilePath the/path/to/serve/from к вашей конфигурации Apache.

Таким образом, вы не раскрываете местоположение файла и сохраняете все управление URL в django.

1 голос
/ 21 апреля 2010

Обслуживание статических файлов с помощью Django - плохая идея, используйте Apache, nginx и т. Д.

https://docs.djangoproject.com/en/dev/howto/static-files/deployment/

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...