Для начала определимся с разницей между статикой и медиа-файлами в терминах Django. Первое — это все ваши файлы, которые вы сами создавали: css-стили, js-скрипты, картинки для дизайна и т.п. Медиа-файлы — всё, что загружает пользователь на ваш сервер (автарки, фотки), т.е. пользовательский контент. С пользовательским контентом всё более-менее просто и поэтому мы рассмотрим настройку только в конце поста.
Честно говоря, я как-то упустил из виду когда появилось встроенное приложение django.contrib.staticfiles, поэтому, столкнулся с ним только на последнем проекте, пришлось потратить какое-то время чтобы понять что к чему и почему не достаточно использовать просто STATIC_ROOT, как раньше.
Итак, сначала ответим на последний вопрос: главная проблема использования в Django просто STATIC_ROOT в качестве указателя пути до статики заключается в том, что не вся наша статика может быть связана с нашим проектом. Ущербность такого подхода ощущал каждый, кто подключал статику встроенной в Django админки на боевом сервере — приходилось либо делать ссылку на папку в дебрях Django со статикой для админки, либо вообще копировать всё оттуда в STATIC_ROOT. А представьте если таких приложений с нужной статикой у вас много — всё собирать ручками занятие не благородное. Более того, статика вообще может лежать какой-нибудь CDN (Content Delivery Network — сеть доставки контента) по типу Amazon S3.
В текущих реалиях в Django мы имеем два «вида» статики:
- Специфичная для приложения, которая, по-хорошему, должна лежать внутри этого приложения в папке static, желательно даже ещё глубже: «/static//» дабы исключить вероятность пересечения путей файлов с другими приложениями.
- Специфичная для проекта статика. Для неё можно создать папку в корне, в примерах назовём эту папку assets.
Первым пунктом можно пренебречь и хранить всё на уровне проекта, если вы не планируете делать переносимое приложение («reusable»), тут есть как плюсы: всё в одном месте, так и минусы: если вы захотите убрать приложение, может потребоваться больше усилий, либо, на больших проектах, это может создать кашу.
При таком подходе настройки STATIC_ROOT и STATICFILES_DIRS должны указывать на следующее:
- STATIC_ROOT — указывает на изначально пустую папку, в которую будет собрана вся статика: как project-wide, так и app-specific. Эту папку, в общем случае, должен обслуживать frontend web-сервер (например, nginx).
- STATICFILES_DIRS — должна содержать путь до assets:
STATICFILES_DIRS = (‘/path/to/assets/’, )
После этого на боевом сервере (читай «DEBUG = False») перед развёртыванием приложения надо выполнить команду:
1 | python manage.py collectstatic |
Которая соберёт все файлы в папку STATIC_ROOT.
Для dev-сервера Django (т.е. если вы используете команду «python manage.py runserver» для разработки) настройка статики закончена и запускать команду collectstatic не обязательно — статика будет подцеплена автоматом. Однако, если вы используете другой сервер для разработки, то вы можете заставить Django обрабатывать статику добавив немного «магии» в ваш urls.py. Также в urls.py надо будет добавить URL для медиа-файлов. Итак, вот фрагменты файла настроек settings.py:
# эта переменная будет указывать на папку проекта
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | PROJECT_ROOT = os.path.dirname(os.path.abspath(__file__)) # путь до папки media, в общем случае она пуста в начале MEDIA_ROOT = os.path.join(PROJECT_ROOT, 'media') MEDIA_URL = '/media/' # URL для медии в шаблонах STATIC_ROOT = os.path.join(PROJECT_ROOT, 'static') # пустая папка, сюда будет собирать статику collectstatic STATIC_URL = '/static/' # URL для шаблонов STATICFILES_DIRS = ( os.path.join(PROJECT_ROOT, 'assets'), ) # "Поисковики" статики. Первый ищет статику в STATICFILES_DIRS, # второй в папках приложений. STATICFILES_FINDERS = ( 'django.contrib.staticfiles.finders.FileSystemFinder', 'django.contrib.staticfiles.finders.AppDirectoriesFinder', ) # Тут должно быть добавлено встроенное в Django приложение для работы со статикой. INSTALLED_APPS = ( <...> 'django.contrib.staticfiles', <...> ) |
А вот содержимое urls.py:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | from django.conf.urls.static import static from django.contrib.staticfiles.urls import staticfiles_urlpatterns from django.conf import settings <..> # В конце файла: if settings.DEBUG: if settings.MEDIA_ROOT: urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) # Эта строка опциональна и будет добавлять url'ы только при DEBUG = True urlpatterns += staticfiles_urlpatterns() |
Напоследок, хочу заметить, что некоторые описанные детали справедливы только для общего случая. Рекомендую также прочитать официальную документацию Django.
Спасибо большое. Кратко и по делу)). Помогло немного разобраться.
Только для Django 1.5 путь для staticfiles_urlpatterns() немного другой:
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
# … the rest of your URLconf here …
urlpatterns += staticfiles_urlpatterns()
http://www.djbook.ru/rel1.5/ref/contrib/staticfiles.html?highlight=staticfiles_urlpatterns#django.contrib.staticfiles.templatetags.staticfiles.django.contrib.staticfiles.urls.staticfi
Спасибо за уточнение, поправим пост.