Как сделать ссылку на скачивание файла django
Для работы с изображениями и другими файлами во фреймворке Python Django существует готовый механизм реализуемый через модели. Процесс хранения картинок и файлов в базах данных может вызвать путаницу если вы не имели особого опыта работы с ними. Процесс создания возможности загрузки файлов состоит из нескольких шагов, которые мы рассмотрим ниже на примерах.
Навигация по посту
Подготовка тестового проекта
Создание модели для загрузки файлов
Каждая модель отображает какую-то таблицу в базе данных. В этих таблицах, а именно колонках, хранятся определенные типы данных (строки, числа и т.д.). Один из таких типов данных - файлы. Однако хранить файлы в SQL базах, в большинстве случаев, считается плохой практикой. Одна из причин не делать этого заключается в непригодности SQL баз в поиске по таким типам данных.
В большинстве случаев хранение файлов организуется в несколько шагов:
Для такой реализации в Django есть два типа полей (Fields):
- FileField - для любых типов данных;
- ImageField - наследует все методы FileField, добавляет валидацию картинок и методы. Например мы можем получить размер картинки используя image.width или image.height.
В ImageField добавлена проверка, что файл имеет тип изображения. Так же у ImageField есть методы возвращающие высоту и ширину. Ширину и высоту так же можно сохранить в отдельные модели используя параметры height_field и width_field. Часть этих возможностей по работе с изображениями выполняется через библиотеку Pillow и поэтому ее нужно установить:
Удаление любого объекта удаляет только запись из базы. На файловой системе файл остается.
После создания моделей выполните миграции:
Динамический upload_to
Папки для сохранения данных можно организовать динамически. Например мы можем сделать так, что бы файл сохранялся в каталог с названием сегодняшней даты формата год-месяц-день:
Этот способ соответствует методу strftime() из библиотеки datetime.
Так же можно создать путь соответствующий пользователю, который выполняет загрузку:
Папка соответствующая пользователю будет создана только в том случае, если модель MyModel будет иметь поле с названием user. Т.е. instance - это и есть сам объект модели. Пример того как это можно сделать:
Использование существующих файлов и папок с FilePathField
Во фреймворке Python Django есть так же поле FilePathField. Его основная задача - создание записи в базе на основании существующего файла.
При определении такого поля Django сканирует указанный путь получая файлы из него и предлагает вам выбор. После выбора файла - путь до него сохраняется в базе:
Доступны поля для рекурсивного поиска и по маске. Path - это абсолютный путь (в отличие от предыдущих примеров).
В панели администрирования, если указанная папка не пуста, файл будет выводиться следующим образом:
FilePathField не следует использовать в директориях с вашим приложением т.к. приводит к уязвимостям.
Используем CRUD запросы в Django 3 на примере приложения
Переменная MEDIA_ROOT и MEDIA_URL
Для Django до 3-ей версии это выглядело так:
Теперь, например, сохранять файлы вы будете по следующему пути:
А открывать их будет по следующей ссылке:
В Django так же есть похожая переменная - STATIC_ROOT и STATIC_URL. Эти переменные указывают на папки в которые вы сами загружали файлы не используя Django. Хоть вы можете соединить STATIC_ROOT и MEDIA_ROOT - это не рекомендуется делать т.к. приведет к уязвимости. Совмещения этих путей стоит избегать.
Панель администрирования
После этого создайте супер пользователя и запустите сервер:
Если открыть директорию прописанную в "MEDIA_ROOT" можно увидеть загруженные файлы (могут отличаться из-за настроек):
Загрузка и вывод файлов
Что бы вывести изображение на странице нужно выполнить следующие шаги:
- Создать url связывающий запрос пользователя с какой-то логикой;
- Шаблон HTML, который преобразует данные и вернет их пользователю;
- Создать функцию или класс, который свяжет url и шаблон.
Реализуем эти пункты
Создание ссылки в urls.py
В вебе есть понятие статических файлов - это любой файл который не изменяясь возвращается пользователю: картинки, видео, файлы css, js и т.д. По умолчанию Django не занимается обработкой таких файлов. Обычно, запросы к статическим файлам обрабатывает другая программа, например веб сервер Nginx.
Вывод изображения на странице
В созданной модели у меня есть 3 поля:
- title - строка;
- cover - картинка;
- book - файл.
Что бы вывести их на странице я создам следующий шаблон по пути:
После запуска сервера можно будет увидеть следующий результат (при наличии данных в базе):
Загрузка документа со страницы и его сохранение
Что бы сохранить файл с Django мы должны использовать следующую функцию:
Теперь, запустив сервер и, открыв главную страницу, у нас будет возможность загрузки файла в корень MEDIA_ROOT:
В примере выше файл в базу не сохраняется. Что бы путь до файла сохранился в базу мы должны передать ему объект file. Ниже пример, если бы вы загружали несколько файлов сразу:
Создание формы
Все шаги, описанные выше, можно сократить использовав существующие возможности Django. Например в Django есть формы, которые можно создать на основе существующей модели. Такие формы упрощают процесс валидации (соответствует ли тип данных Django типу в базе), представления в шаблоне (HTML теги создаются сами) и много другое.
Для работы формы нужна модель, на основе которой можно определить поля. Поместим в этот файл следующий код:
В файл маршрутизации добавим маршрут, который свяжет url с новым классом:
Читайте также: