Found misprint?

Select it with the mouse and hit Enter

Ctrl-Enter
Processed:
38 1 199 25
The full repository of DjangoBook translation you can get on GitHub.
We appreciate your patches!
We are glad to hear your questions, comments or suggestions!
(Open in new tab)
Users number: 638
Русская группа
на Google
на поддержку перевода
Яндекс Яндекс.Деньги Хочу такую же кнопку
Ускорить процесс перевода!

ЯМ:41001223475816

Работа с файлами в Django

Основы

Это перевод постов из одного интересного блога. Оригинал ч.1, ч.2 и ч.3.

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

  1. Файла прописанные в коде и в шаблонах, назовем их STATIC файлы.
  2. Файлы, который используются в коде, но известны только в процессе работы кода, назовем их MEDIA файлы. Прим.: например файлы загруженные пользователем. Имя файлы мы не знаем и в коде оно не прописано.

Это уловная классификация и основана на определениях из документации Django.

Так как файлы хранятся на диске или других storage backend лучше всего отдавать их через быстрый сервер HTTP и пусть Django обрабатывать только динамический контент.

Настройка

Рассмотрим один из вариантов настройки:

import os

_PATH = os.path.abspath(os.path.dirname(__file__))

MEDIA_ROOT = os.path.join(_PATH, 'files', 'media')
MEDIA_URL = '/media/'

STATIC_ROOT = os.path.join(_PATH, 'files', 'static')
STATIC_URL = '/static/'
STATICFILES_DIRS = (
    os.path.join(_PATH, 'static'),
)
STATICFILES_FINDERS = (
    'django.contrib.staticfiles.finders.FileSystemFinder',
    'django.contrib.staticfiles.finders.AppDirectoriesFinder',
)

ADMIN_MEDIA_PREFIX = '/static/admin/'

Что такое _PATH должно быть понятно. В проекте находится папка files, которая содержит папку media для MEDIA файлов и папка static для STATIC файлов. Очень важно разделить их таким образом. Потом можете получить много проблем не разделим их изначально. Это позволит вам легко использовать различные версии файлов, расположив их по разным папкам.

Но почему files в папке проекта? Потому что это удобно при разработке. На "продакшине" рекомендуется вынести files из проекта и изменить MEDIA_ROOT и STATIC_ROOT.

STATIC файлы располагаются в <_PATH>/static. Это используемые js и css файлы. Приложение django.contrib.staticfiles соберет все STATIC файлы из STATICFILES_DIRS и из соответствующих папок приложение и перенесет в STATIC_ROOT.

Подведем итоги:

  • В STATIC добавляются файлы из проекта(смотрите STATICFILES_DIRS и FileSystemFinder), а так же AppDirectoriesFinder добавит файлы из папки static в приложениях.
  • MEDIA и STATIC файла лучше разделить(смотрите STATIC_ROOT и MEDIA_ROOT).
  • STATIC_ROOT и MEDIA_ROOT лучше вынести из проекта на "продакшине".

И не забудьте добавить "слеш" в конце STATIC_URL и MEDIA_URL!

Как настроить выдачу файлов для dev-сервера

Как упоминалось выше, лучше отдавать файлы через специальный сервер, например Nginx или Apache. Но при разработке это лишние проблемы. Можно легко настроить выдачу файлов средствами Django. Предполагается что при разработке DEBUG всегда True, а на сервере - False. Добавим в urls.py:

from django.conf.urls.static import static
from django.contrib.staticfiles.urls import staticfiles_urlpatterns

urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
urlpatterns += staticfiles_urlpatterns()

Все просто. Учтите что urlpatterns изменится только при DEBUG == True и если MEDIA_URL и STATIC_URL не абсолютны(то есть без http://).

Как использовать STATIC файлы в шаблонах

Для создания URL к файлу можно просто добавить STATIC_URL и расположение относительно папки static:

<img src="{{ STATIC_URL }}myapp/img/logo.png" />

Что бы STATIC_URL был доступен в шаблоне, необходимо:

  1. Шаблон должен быть "rendered" с RequestContext
  2. django.core.context_processors.static должен быть добавлен в TEMPLATE_CONTEXT_PROCESSORS(прим.: уже добавлен по-умолчанию).

Если по каким-то причинам условия не соблюдены используем:

{% load static %}
{% get_static_prefix as STATIC_URL %}

<img src="{{ STATIC_URL }}myapp/img/logo.png" />

Как использовать MEDIA файлы в шаблоне

Это на много проще. Объект FieldFile, возвращаемый ImageField и FileField, содержит path и url:

<img src="{{ some_model.some_image_field.url }}" />

Как добавить STATIC файлы

Так как имена STATIC файлов используются в коде, шаблонах, лучше всего хранить их в VCS вместе с кодом. STATIC файлы собираются(находят и копируются или через simlink) с помощью "finder"-ов. Вам не обязательно знать как все это происходит, главное хранить файлы в нужном месте.

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

$ ls -1
models.py
static/
templates/
views.py

Файлы, которые относятся конкретно к проекту нужно хранить в папка указанных в STATICFILES_DIRS:

>>> from django.conf import settings
>>> settings.STATICFILES_DIRS
('/opt/myproject/src/project/static',)

Как загрузить MEDIA файлы

MEDIA файлы в основном используются в моделях с полями FileField и ImageField. Например:

# models.py
from django.db import models
from django.forms.models import modelform_factory

class MediaModel(models.Model):
    media_file = models.FileField(upload_to='user_media')

MediaForm = modelform_factory(MediaModel)

# views.py
def media_create(request):
    if request.method == "POST":
        form = MediaForm(request.POST, request.FILES)
        if form.is_valid():
            form.save()
            return HttpResponseRedirect(reverse('media-list'))
    else:
        form = MediaForm()
    return render_to_response('usermedia/create/html', {'form': form})