Как в django хранить файлы

Обновлено: 04.07.2024

AWS S3-это отличный и недорогой сервис для хранения файлов. В этой статье мы будем использовать Python и Django для загрузки файлов в AWS S3.

Вступление

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

Разрешая пользователям загружать файлы, мы можем позволить им делиться фотографиями, видео или музыкой с другими или создавать резервные копии для безопасного хранения. Мы также можем предоставить функциональность для управления файлами и преобразования их в другие форматы через веб-сайты вместо установки собственных приложений.

Рост социальных сетей во всем мире можно объяснить способностью пользователей загружать свои файлы, в основном в виде изображений и видео для просмотра другими пользователями, а также в качестве средства коммуникации. Предоставляя пользователям возможность загружать файлы на веб-сайты и платформы, средства коммуникации были усовершенствованы, и теперь информация может распространяться в самых разных форматах.

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

Как Django Обрабатывает Файловое Хранилище

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

Прежде чем файл будет сохранен, он временно хранится где-то, прежде чем быть обработанным и сохраненным в предполагаемом конечном местоположении. Например, если загруженный файл меньше 2,5 МБ, содержимое этого файла будет сохранено в памяти, а затем записано на диск после завершения всех операций при его обработке.

Это делает процесс быстрым для небольших файлов. Для файлов размером более 2,5 МБ они сначала записываются во временное место по мере получения данных, а затем, как только обработка завершена, файл перемещается в конечный пункт назначения.

Поведение файлов в Django можно настроить с помощью различных настроек, таких как FILE_UPLOAD_MAX_MEMORY_SIZE , что позволяет нам изменить предельный размер загрузки 2,5 МБ для файлов, которые сначала записываются в память, а не во временное место. Мы также можем настроить разрешения по умолчанию для загруженных файлов через FILE_UPLOAD_PERMISSIONS .

Другие настройки можно найти в этом разделе официальной документации Django.

Где мы можем хранить наши файлы?

Стремясь сократить расходы на обслуживание сервера и повысить производительность, мы также можем отказаться от хранения загруженных файлов на наших собственных серверах. В этом случае мы можем передать их другим поставщикам размещенных хранилищ, таким как AWS , Azure или OneDrive , среди прочих.

Существует несколько пакетов, которые позволяют нам взаимодействовать с API, предоставляемыми различными поставщиками услуг, о которых мы упоминали. Они включают в себя:

    позволяет нам хранить наши загруженные файлы в AWS Simple Storage Service (S3), Dropbox, OneDrive, Azure и Digital Ocean . через который мы можем загружать файлы непосредственно в Amazon S3 , который позволяет нам взаимодействовать с Rackspace для наших нужд хранения
  • Другие включают Django-Dropbox , Django-Storage-Swift и Django-Cloudinary-Storage . Подробнее можно найти здесь

Для этого поста мы будем использовать пакет Django-s3direct для хранения наших файлов на Aws S3.

Мы будем использовать Django для создания веб-приложения, в котором мы будем загружать контент для просмотра конечными пользователями. Это будет достигнуто с помощью интерфейса администрирования Django, который поставляется вместе с фреймворком.

Наш сайт будет использоваться для продажи автомобилей, и на нем мы будем отображать детали и добавлять изображения или видео продаваемых автомобилей.

Изображения или видео автомобилей, выставленных на продажу, будут храниться на S3. Мы не будем осуществлять регистрацию пользователя или вход в систему в настоящее время для краткости.

Установка

Мы будем использовать Pipenv для настройки и управления нашей изолированной средой, в которой мы будем создавать наше приложение Django, выполнив следующую команду для его настройки с помощью Python3:

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

Django предоставляет набор команд для начальной загрузки нашего проекта, прежде чем мы начнем реализовывать основную функциональность нашего приложения. Наш проект Django drive будет иметь одно приложение, которое будет в центре внимания этого поста. Для этого мы запускаем следующие команды:

Проект django-admin startproject . команда создает проект, а django-admin startapp . команда создает приложение.

Последний шаг нашей настройки-создание таблиц базы данных с помощью команды migrate :

Когда мы начинаем наш проект, выполнив команду python manage.py runserver , нас приветствует следующая страница, которая подтверждает, что наша настройка прошла успешно:

Поскольку мы будем загружать наши файлы в AWS S3, нам нужно будет создать бесплатный уровень аккаунт AWS для демонстрационных целей. После настройки мы можем перейти на панель мониторинга S3 и создать новое ведро, которое будет содержать наши загрузки.

Чтобы Django-s3direct взаимодействовал с нашей настройкой AWS, нам необходимо предоставить следующие учетные данные AWS_ACCESS_KEY_ID , AWS_SECRET_ACCESS_KEY и AWS_STORAGE_BUCKET_NAME .

Далее мы добавим следующее к вашему django_drive/settings.py файл:

Django-s3direct позволяет нам указать более одного места назначения для наших загрузок, таким образом, мы можем направлять различные файлы в отдельные сегменты S3. Для этого проекта мы поместим все загрузки в одно ведро. Еще одна интересная особенность заключается в том, что мы также можем ограничить типы файлов, которые могут быть загружены на наш веб-сайт. В нашем случае мы ограничили его только MP4-видео, JPEG-и PNG-изображениями.

Примечание: Более подробную информацию о настройке Django-s3direct , например CARS и Access Setup , можно найти здесь .

Нам также нужно добавить следующие записи в django_drive/urls.py файл:

Реализация

Мы начнем с создания модели для наших автомобильных данных, которая будет отображаться конечным пользователям. Эта модель также определит информацию, которую мы будем вводить в нашу панель администратора при добавлении автомобилей на нашу платформу. Модель автомобиля будет выглядеть следующим образом:

Для каждого автомобиля мы будем хранить его название, год выпуска, цену и изображение или видео. После создания модели давайте сделаем миграции, чтобы создать таблицу в базе данных, которая будет содержать наши данные, запустив:

Поскольку мы будем использовать панель администратора Django для управления автомобилями на нашей платформе, нам нужно зарегистрировать нашу модель в django_drive_app/admin.py :

Затем нам нужно создать суперпользователя, который будет отвечать за добавление автомобилей, выполнив следующую команду и следуя подсказкам:

python manage.py команда runserver просто перезапускает ваше приложение.

Это форма, которую мы используем для добавления автомобиля и его деталей:

Как только мы сохраним наш автомобиль, мы сможем найти изображение, которое мы загрузили в наше ведро S3 на консоли AWS. Это означает, что ваш файл был загружен в AWS.

Теперь мы создадим представление для отображения автомобилей и их данных конечным пользователям нашего веб-сайта, а также для отображения изображений или видео, связанных с каждым автомобилем. Мы начнем с создания представления в django_drive_app/views.py :

В этом представлении мы используем class-based Django view для рендеринга HTML-файла для отображения наших автомобилей. На наш взгляд, мы запускаем запрос, чтобы получить все автомобили, хранящиеся в нашей базе данных.

Далее создадим django_drive_app/templates/django_drive_app/cars.html рендерить наши автомобили:

Имея представление и шаблон на месте, давайте добавим конечную точку, которая будет использоваться для отображения списка автомобилей конечным пользователям, создав django_drive_app/urls.py :

Мы импортируем наше представление и добавляем запись URL-адреса, чтобы сопоставить конечную точку с представлением, которое будет отображать автомобили. Когда мы перезапускаем наш сервер и переходим к 127.0.0.1:8000/cars/ , мы сталкиваемся со следующим:

Как мы видим, мы создали автомобили с прикрепленными изображениями и видео и загрузили их в сервис Aws S3. Те же изображения и видео были отрисованы в нашем веб-приложении после получения из AWS.

Вывод

В этой статье мы создали простое приложение Django, которое позволяет администраторам загружать файлы в AWS S3 через панель администрирования Django. Мы визуализировали загруженные файлы, размещенные на S3 на вашей целевой странице, включая видео и изображения автомобилей, которые пользователи хотели бы приобрести или просмотреть.

Мы использовали библиотеку Django-s3direct для обработки взаимодействия между нашим приложением Django и AWS S3, где хранятся наши файлы. С помощью приложения администрирования Django мы смогли загрузить файлы, которые в конечном итоге были представлены конечным пользователям на нашей целевой странице. Мы могли загружать и визуализировать как изображения, так и видео.

В этом документе описываются API-интерфейсы Django для доступа к файлам, например загруженным пользователем. API нижнего уровня достаточно общие, чтобы вы могли использовать их для других целей. Если вы хотите работать со «статическими файлами» (JS, CSS и т. Д.), См. Управление статическими файлами (например, изображениями, JavaScript, CSS) .

По умолчанию, Django хранит файлы локально, используя MEDIA_ROOT и MEDIA_URL настройку. В приведенных ниже примерах предполагается, что вы используете эти значения по умолчанию.

Однако Django предоставляет способы написания собственных систем хранения файлов, которые позволяют полностью настраивать, где и как Django хранит файлы. Вторая половина этого документа описывает, как работают эти системы хранения.

Использование файлов в моделях ¶

Когда вы используете FileField или ImageField , Django предоставляет набор API, которые вы можете использовать для работы с этим файлом.

Рассмотрим следующую модель, использующую ImageField для хранения фотографии:

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

Этот объект - car.photo в примере - является File объектом, что означает, что он имеет все методы и атрибуты, описанные ниже.

Файл сохраняется как часть сохранения модели в базе данных, поэтому на фактическое имя файла, используемое на диске, нельзя полагаться до тех пор, пока модель не будет сохранена.

Например, вы можете изменить имя файла, name установив путь к файлу относительно местоположения хранилища файлов ( MEDIA_ROOT если вы используете значение по умолчанию FileSystemStorage ):

Хотя в экземпляре доступны ImageField атрибуты данных, не относящиеся к изображению, такие как height , width и size , базовые данные изображения нельзя использовать без повторного открытия изображения. Например:

File Объект ¶

Внутри Django использует django.core.files.File экземпляр каждый раз, когда ему нужно представить файл.

В большинстве случаев вы будете использовать то, File что вам предоставил Django (то есть файл, прикрепленный к модели, как указано выше, или, возможно, загруженный файл).

Если вам нужно построить File самостоятельно, самый простой способ - создать его с помощью встроенного file объекта Python :

Теперь вы можете использовать любые задокументированные атрибуты и методы File класса.

Имейте в виду, что файлы, созданные таким образом, не закрываются автоматически. Для автоматического закрытия файлов можно использовать следующий подход:

Закрытие файлов особенно важно при доступе к полям файла в цикле по большому количеству объектов. Если файлы не закрываются вручную после доступа к ним, может возникнуть риск нехватки файловых дескрипторов. Это может привести к следующей ошибке:

Файловое хранилище ¶

За кулисами Django делегирует решения о том, как и где хранить файлы, системе хранения файлов. Это объект, который на самом деле понимает такие вещи, как файловые системы, открытие и чтение файлов и т. Д.

Хранилище файлов по умолчанию в Django задается DEFAULT_FILE_STORAGE параметром; если вы явно не укажете систему хранения, она будет использоваться.

См. Ниже подробные сведения о встроенной системе хранения файлов по умолчанию и см. Создание собственной системы хранения для получения информации о создании собственной системы хранения файлов.

Объекты хранения ¶

Хотя большую часть времени вы хотите использовать File объект (который делегирует надлежащее хранилище для этого файла), вы можете напрямую использовать системы хранения файлов. Вы можете создать экземпляр некоторого настраиваемого класса хранилища файлов или, что часто более полезно, вы можете использовать глобальную систему хранения по умолчанию:

См. API хранилища файлов для API хранилища файлов.

Класс хранилища встроенной файловой системы ¶

Django поставляется с django.core.files.storage.FileSystemStorage классом, который реализует базовое хранилище файлов локальной файловой системы.

Например, следующий код будет хранить загруженные файлы /media/photos вне зависимости от ваших MEDIA_ROOT настроек:

Пользовательские системы хранения работают одинаково: вы можете передать их в качестве storage аргумента в файл FileField .

Использование вызываемого ¶

Вы можете использовать вызываемый объект в качестве storage параметра для FileField или ImageField . Это позволяет вам изменять используемое хранилище во время выполнения, например, выбирая разные хранилища для разных сред.

Ваш вызываемый объект будет оцениваться при загрузке классов ваших моделей и должен возвращать экземпляр Storage .

Для работы с изображениями и другими файлами во фреймворке Python Django существует готовый механизм реализуемый через модели. Процесс хранения картинок и файлов в базах данных может вызвать путаницу если вы не имели особого опыта работы с ними. Процесс создания возможности загрузки файлов состоит из нескольких шагов, которые мы рассмотрим ниже на примерах.

Навигация по посту

Подготовка тестового проекта

Добавление приложения Django в INSTALLED_APPS

Выполнение migrate в Django

Создание модели для загрузки файлов

Каждая модель отображает какую-то таблицу в базе данных. В этих таблицах, а именно колонках, хранятся определенные типы данных (строки, числа и т.д.). Один из таких типов данных - файлы. Однако хранить файлы в SQL базах, в большинстве случаев, считается плохой практикой. Одна из причин не делать этого заключается в непригодности SQL баз в поиске по таким типам данных.

В большинстве случаев хранение файлов организуется в несколько шагов:

Для такой реализации в Django есть два типа полей (Fields):

  • FileField - для любых типов данных;
  • ImageField - наследует все методы FileField, добавляет валидацию картинок и методы. Например мы можем получить размер картинки используя image.width или image.height.

Создание модели с ImageField и FileField в Django

В ImageField добавлена проверка, что файл имеет тип изображения. Так же у ImageField есть методы возвращающие высоту и ширину. Ширину и высоту так же можно сохранить в отдельные модели используя параметры height_field и width_field. Часть этих возможностей по работе с изображениями выполняется через библиотеку Pillow и поэтому ее нужно установить:

Удаление любого объекта удаляет только запись из базы. На файловой системе файл остается.

После создания моделей выполните миграции:

Динамический upload_to

Папки для сохранения данных можно организовать динамически. Например мы можем сделать так, что бы файл сохранялся в каталог с названием сегодняшней даты формата год-месяц-день:

Этот способ соответствует методу strftime() из библиотеки datetime.

Так же можно создать путь соответствующий пользователю, который выполняет загрузку:

Папка соответствующая пользователю будет создана только в том случае, если модель MyModel будет иметь поле с названием user. Т.е. instance - это и есть сам объект модели. Пример того как это можно сделать:

Сохранение картинки в папку пользователя Djagno

Использование существующих файлов и папок с FilePathField

Во фреймворке Python Django есть так же поле FilePathField. Его основная задача - создание записи в базе на основании существующего файла.

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

Доступны поля для рекурсивного поиска и по маске. Path - это абсолютный путь (в отличие от предыдущих примеров).

В панели администрирования, если указанная папка не пуста, файл будет выводиться следующим образом:

Выбор существующего файла с FilePathField Django

FilePathField не следует использовать в директориях с вашим приложением т.к. приводит к уязвимостям.

Используем CRUD запросы в Django 3 на примере приложения

Переменная MEDIA_ROOT и MEDIA_URL

Для Django до 3-ей версии это выглядело так:

Определение MEDIA_ROOT и MEDIA_URL в Django

Теперь, например, сохранять файлы вы будете по следующему пути:

А открывать их будет по следующей ссылке:

В Django так же есть похожая переменная - STATIC_ROOT и STATIC_URL. Эти переменные указывают на папки в которые вы сами загружали файлы не используя Django. Хоть вы можете соединить STATIC_ROOT и MEDIA_ROOT - это не рекомендуется делать т.к. приведет к уязвимости. Совмещения этих путей стоит избегать.

Панель администрирования

Создание панели администрирования в Django

После этого создайте супер пользователя и запустите сервер:

Создание пользователя администратора в Django

Загрузка файлов и картинок в панели администрирования Django

Если открыть директорию прописанную в "MEDIA_ROOT" можно увидеть загруженные файлы (могут отличаться из-за настроек):

Папка с сохранёнными файлами в Django

Загрузка и вывод файлов

Что бы вывести изображение на странице нужно выполнить следующие шаги:

  1. Создать url связывающий запрос пользователя с какой-то логикой;
  2. Шаблон HTML, который преобразует данные и вернет их пользователю;
  3. Создать функцию или класс, который свяжет url и шаблон.

Реализуем эти пункты

Создание ссылки в urls.py

В вебе есть понятие статических файлов - это любой файл который не изменяясь возвращается пользователю: картинки, видео, файлы css, js и т.д. По умолчанию Django не занимается обработкой таких файлов. Обычно, запросы к статическим файлам обрабатывает другая программа, например веб сервер Nginx.

Включение поддержки загруженных файлов с DEBUG в Django

Вывод изображения на странице

В созданной модели у меня есть 3 поля:

  • title - строка;
  • cover - картинка;
  • book - файл.

Что бы вывести их на странице я создам следующий шаблон по пути:

Создание шаблона и вывод файла на странице в Django

После запуска сервера можно будет увидеть следующий результат (при наличии данных в базе):

Вывод файла и картинки в Django

Загрузка документа со страницы и его сохранение

Что бы сохранить файл с Django мы должны использовать следующую функцию:

Загрузка файла в Django используя request.FILES

Теперь, запустив сервер и, открыв главную страницу, у нас будет возможность загрузки файла в корень MEDIA_ROOT:

В примере выше файл в базу не сохраняется. Что бы путь до файла сохранился в базу мы должны передать ему объект file. Ниже пример, если бы вы загружали несколько файлов сразу:

Создание формы

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

Для работы формы нужна модель, на основе которой можно определить поля. Поместим в этот файл следующий код:

Создание формы ModelForm Django

Вывод формы для загрузки файлов с CreateView в Django

В файл маршрутизации добавим маршрут, который свяжет url с новым классом:


В этой статье мы рассмотрим, как использовать Django и его остальную среду для реализации хранилища данных. Мы особенно сосредоточимся на источниках данных, которые поступают из внешних API, но тот же принцип может быть применен к любым другим типам источников данных: плоские файлы или прямые соединения ODBC.

Одним из основных преимуществ использования Django для реализации хранилища данных является то, что вы будете иметь возможность использовать Python для каких-либо компонентов или задач: ETL, запрашивая, манипулирование данных, отчетность, веб-приложение приложений .

Пожалуйста, обратите внимание, что Django не может быть правильным решением для Вашего случая использования, однако те же принципы могут быть применены.

Весь код, используемый в этой статье, можно найти наGitHub,

Что такое хранилище данных?

Хранилища данных обычно реализуется для консолидации различных источников данных по всей компании. В нашем случае, мы используем различные внешние и внутренние интерфейсы, чтобы объединить все эту информацию для анализа, отчетности и прогностического моделирования.

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

Мы рассмотрим эти проблемы в деталях в следующих разделах.

Джанго и остальные рамки

Django - это шаблон веб-фреймворка с открытым исходным кодом; и следует модель, вид, Template (МВТ) шаблонов проектирования.

В этой статье мы сосредоточимся в основном на компоненте Model архитектуры Django. Чтобы иметь возможность взаимодействовать с базой данных, Django использует Object Relational Mapper; Это означает, что вместо того, чтобы с помощью таблиц SQL они будут представлены в виде классов Python. Это означает, что мы можем выполнять любые операции CRUD с использованием Python без необходимости непосредственного взаимодействия с SQL или самой базой данных.
Это будет иметь ключевое значение в реализации нашего хранилища данных, как мы будем использовать этот ОРМ для выполнения вставки и обновления.

Базовая модель

Models.pyбудет содержать всю логику, которая позволяет Django ORM взаимодействовать с базой данных; каждый из класса вmodels.pyэто физическая таблица в базе данных

В этом примере мы собираемся создать 3 таблицы:
-Человек; экземпляр физического лица однозначно идентифицируется своим именем и фамилией
-Транспортное средство; транспортное средство однозначно идентифицируется его регистрационный номер
-PersonVehicle; пример владения автомобилем лицом

создан в,updated_at2 автоматически сгенерированных поля, которые будут записывать дату и время, когда запись была создана или обновлена.

PROTECTзапрещают любое удаление записей с отношениями с другими таблицами. Вы также можете использоватьCASCADEесли вы хотите, чтобы удалить все записи, относящиеся к этой записи.

Теперь, когда мы создали нашу модель, мы можем вставить информацию через оболочку Django (./manage.py shell):


Отслеживание изменений

Обратите внимание, что мы добавляем полеисторияв каждой модели, где мы хотим отслеживать изменения с течением времени. Эти изменения будут сохранены в зеркальной таблице с префиксомистория,

Чтобы иметь возможность отслеживать изменения, мы также должны определитьсуррогатные ключи,эти ключи бизнес определение уникальности записи. Например, вЧеловекТаблица, которую мы определилиимяа такжефамилиякакunique_togetherЭто означает, что эти поля не будут обновляться, однакоЭл. адресявляется.

Теперь давайте попробуем изменить запись, которую мы записали ранее:



сериализаторы

Как объяснялось ранее, сериализаторов будет использоваться для анализа и проверки входных данных, прежде чем вставить его в соответствующих таблицах SQL

Теперь давайте предположим, что внешний источник предоставляет нам информацию через REST API в следующем формате JSON:


JSON предоставляет личность человека и список транспортных средств, которые в настоящее время принадлежат этому человеку, ниже приведены сериализаторы, которые будут использоваться для анализа этого JSON:

Во-первых, мы создали вложенный сериализаторVehicleSerializerкоторый анализирует экземпляр одного транспортного средства, затем в родительском сериализатореPersonVehicleSerializerмы можем использовать аргументмного = Trueсказать Джанго, что они могут быть несколькими транспортными средствами.

Чтобы сохранить всю информацию правильно, мы перезаписываемспасти()метод, сначала мы создаем или обновляемЧеловекзатем для каждого транспортного средства во вложенном словаре мы создаемТранспортное средствоа затем связать его сЧеловеквPersonVehicle,


Обратите внимание, что сериализаторы можно обогатить, добавив правила проверки или преобразования, если это будет необходимо, как в традиционной реализации ETL.

Взгляды

В предыдущем примере мы использовали файл JSON и оболочку Django для вставки данных в наше хранилище данных.

Теперь давайте предположим, что информация не предоставляется внешним поставщиком, но исходная система архитектуры компании отправляет информацию в хранилище данных. Это может быть достигнуто путем добавленияПосмотретьчто позволит вставить данные черезПОСЛЕЗапрос API.

Как видите, мы используем ту же последовательность, которую мы использовали в оболочке Django, но используяapi_viewдекоратор для предоставления этой конечной точки другой системе или пользователю. Это означает, что теперь мы можем общаться с нашим хранилищем данных из любой системы (вам нужно убедиться, что ваш сервер Django работает).


Вывод

В этой статье мы рассмотрели все этапы и компоненты построения хранилища данных с помощью Django:
- Используйте Django ORM для создания 3-й нормальной модели данных формы;
- использовать простую историю, чтобы отслеживать изменения во времени;
- использовать сериализатор остальной инфраструктуры для десериализации информации, поступающей от внешних поставщиков или внутренних систем, и сохранять результаты в хранилище данных; а также
- Используйте представления из остальной структуры, чтобы исходные системы могли отправлять информацию через запрос POST.

Все вышеперечисленное должно дать достаточно информации для построения вашего хранилища данных, конечно, вам нужно будет просмотреть все различные источники, понять, как эти данные будут использоваться в нисходящем направлении для наиболее эффективного моделирования данных, и добавить все преобразования / проверки. правила в вашем ETL.

Читайте также: