Как вернуть статические файлы, проходящие через представление в django?

10

Мне нужно вернуть файлы css и js файлы в соответствии с определенной логикой. Ясно, что статическая подача не выполняет то, что мне нужно. У меня есть представление, метод визуализации которого использует логику для поиска нужного файла, но тогда я должен вернуть его. Технически я могу просто прочитать файл и добавить его в объект HttpResponse с соответствующим типом mime, но мне было интересно, есть ли лучшая стратегия. (например, fpassthru() в php)

  • 1
    Какой из них не выполняет то, что вам нужно, статическое обслуживание файлов веб-сервера или django.views.static.serve ?
  • 0
    ни один из двух :)
Показать ещё 3 комментария
Теги:

7 ответов

16

Это то, что я использовал:

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
    Мне нужен был режим 'rb' для функции open (), или этот код испортил мои PDF-файлы. Это соответствует коду, используемому в django / views / static.py.
  • 2
    Мне кажется, что это вызывает загрузку всего файла в память. Не так ли?
Показать ещё 2 комментария
8

Какое программное обеспечение веб-сервера вы используете?

По крайней мере, для Apache и NginX существует модуль, позволяющий использовать заголовок X-SendFile HTTP. Сайт NginX говорит, что Lighty тоже может это сделать.

В представлении оболочки:

...

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

Затем вы можете подключить представление через http://mysite.com/url_path/to/serve_hidden_css_file/.

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

Для Apache: http://tn123.ath.cx/mod_xsendfile/
Для NginX: http://wiki.nginx.org/NginxXSendfile

4

Почему бы вам не использовать статические файлы Django внутри вашего представления

from django.contrib.staticfiles.views import serve

...
def view_function(request):
   return serve(request, 'absolute_path_to_file_name')
  • 8
    В документах говорится: «Предупреждение. Это представление будет работать только в том случае, если DEBUG имеет значение True. Это потому, что это представление крайне неэффективно и, вероятно, небезопасно. Оно предназначено только для локальной разработки и никогда не должно использоваться в производстве».
1

Обслуживание файлов непосредственно из представления происходит очень медленно. Если вы ищете обычную файловую службу, см. Этот вопрос: Наличие Django для загрузки файлов

Чтобы очень легко обслуживать файлы с помощью представления (например, для целей отладки), продолжайте чтение.

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

Это позволяет загрузить файл с: http://127.0.0.1:8080/app/test-files/myxml/

1

Почему бы не вернуть HttpResponseRedirect в местоположение правильного статического файла?

  • 2
    потому что файл не доступен напрямую.
1

Передайте итератору (например, результат open()) конструктору HttpResponse.

0

Нельзя использовать django для обслуживания статического контента (не говоря уже, на несколько порядков медленнее).

Я предпочел бы преобразовать представление в процессор контекста и использовать переменные в шаблонах, чтобы найти, какие блоки включать.

  • 0
    это именно то, от чего я хочу отойти. Я уже включил материал, в результате чего файлы CSS и JS включены жестко закодированы в файл HTML, предотвращая любую форму кэширования (так как считается, что страница в целом меняется). Я хочу иметь возможность отправлять js и css, но так как эта поставка зависит от доступных плагинов моего приложения, мне нужно выполнить некоторую логику перед отправкой файла.
  • 0
    Вы имеете в виду предотвращение любой формы кэширования Django? Потому что включение в шаблон жестких кодов css & js не остановит их кэширование браузером пользователя. Мне не ясно, в чем собственно проблема. Похоже, у вас возникли проблемы с кэшированием всей страницы из-за динамических включений. Почему бы не кэшировать оставшуюся часть страницы и позволить браузеру / вашему веб-серверу делать все остальное (в любом случае, это его работа)?
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню