Это перевод постов из одного интересного блога. Оригинал ч.1, ч.2 и ч.3. Описанный подход работает для Django 1.3 и выше.
В этой статье под файлом подразумевается все, что не генерируется динамически. Есть два типа файлов, с которыми работают веб-приложения:
- Файла прописанные в коде и в шаблонах, назовем их
STATIC
файлы. - Файлы, который используются в коде, но известны только в процессе работы кода, назовем их
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 файлы в шаблонах
{% load staticfiles %}
<img src="{% static '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})