Программы
Добавляем поддержку медиа-файлов в Django проект

Добавляем поддержку медиа-файлов в Django проект

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

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

Для этого в Django есть django.db.models.ImageField. Добавив это поле, мы определяем, что в нашей модели есть поле с изображением, а в админке появляется и возможность загрузить его. Другое дело, не понятно куда оно будет загружено, как его вывести на сайте.

Что ж, приступим! Начнём файла настроек settings.py:

MEDIA_ROOT = f'{BASE_DIR}/media'
MEDIA_URL = '/media/'

Здесь мы указываем, в какой директории будут храниться сами файлы (MEDIA_ROOT), а также по какому префиксу url будут искаться при запросе от клиента (MEDIA_URL).

Также помним, что BASE_DIR указывает на корень проекта. Так что при этих настройках директория для медиа-файлов будет в той же папке, что и директории наших приложений. Если хотите, чтобы файлы хранились вне папки с кодом Django-проекта, то MEDIA_ROOT = f'{BASE_DIR}/../media' - будет как раз на уровень выше.

Далее добавим связь MEDIA_URL к MEDIA_ROOT, чтобы данный префикс вёл на файлы. Делаем это в urls.py:

from django.contrib import admin
from django.urls import path
from django.conf import settings
from django.conf.urls.static import static

urlpatterns = [
    path('admin/', admin.site.urls),
    ...
]

if settings.DEBUG:
    urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

Как можно заметить, включаем эти url-ы только в случае отладки (во время разработки) так как django-сервер для разработки не предназначен для боевых серверов.

На боевых же серверах у вас Django, скорее всего, будет стоять за высокопроизводительным сервером, например, nginx. Поэтому пусть nginx и займётся работой со статическими файлами. Для nginx нужно будет в конфигурационном файле указать настройку location:

location ~* /media/.*?\.(html|txt|jpg|jpeg|gif|png|pdf|ico|css|bmp|js|swf|otf|woff|ttf|gz|svg|ogg)$ {
    root /путь/до/папки/media;
    expires 30m;
    add_header Cache-Control public;
}

Далее посмотрим на модель данных:

from django.db import models


class Product(models.Model):
    img = models.ImageField(upload_to='product', null=True, blank=True, verbose_name='Изображение')
    ...

Советую указать параметр upload_to - будет создана поддиректория в MEDIA_ROOT, в которой будут храниться изображения для этой модели. Это более удобный способ хранения файлов, чем хранить всё в одной "куче".

Само же изображение в templates выводится просто:

<img src="{{ object.img.url }}" />
Изображение Python 3.11. Что нового?