Как сохранить файл в базу данных django

Обновлено: 29.06.2024

В этом документе описываются 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 .

On the command line, navigate there and create a directory insta for our files. We will use Pipenv to install both Django and pillow which is a Python image process library Django relies on for image files. For non-image file uploads, pillow is not needed. Finally activate our new virtual environment with the shell command.

Project and App

Now create our new Django project called insta_project and a new app called posts .

Now run python manage.py migrate to setup the new database for our project.

Models

If we wanted to use a regular file here the only difference could be to change ImageField to FileField .

MEDIA_ROOT

Open up insta_project/settings.py in your text editor. We will add two new configurations. By default MEDIA_URL and MEDIA_ROOT are empty and not displayed so we need to configure them:

  • MEDIA_ROOT is the absolute filesystem path to the directory for user-uploaded files
  • MEDIA_URL is the URL we can use in our templates for the files

Admin

Now update the posts/admin.py file so we can see our Post app in the Django admin.

Then run migrate to update the database.

Now we can create a superuser account to access the admin and then execute runserver to spin up the local web server for the first time.

Admin Homepage

Django Pony Post

Upon "Save" you will be redirected to the Posts page where we can see all our posts.

Image Posts

The confusing thing about Django is that you often need 4 different but interconnected files for one webpage: models.py , urls.py , views.py , and a template html file. I find it easiest to reason about this by going in order from models -> urls -> views -> template files. Our model is already done so that means diving into URL routes.

Views

We can use the generic class-based ListView here, import our Post model, and then create a HomePageView that uses the model and a template called home.html .

Boom! Moving on the last step is that template file called home.html .

Templates

We tell Django to also look here for any templates by updating the TEMPLATES configuration within insta_project/settings.py .

Our home.html template file will display the title and image for all posts. Just like Instagram would :)

Homepage

And voila! If you add additional posts with a title and image via the admin they will appear on the homepage.

Next up that form. First create it.

Then create the new template.

Create Post

Next Steps

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

Основы загрузки файлов с Django

Когда файлы передаются на сервер, данные файла в конечном итоге помещаются в request.FILES .

Для формы HTML обязательно должен быть правильно установлен атрибут enctype="multipart/form-data" . В противном случае r equest.FILES будет пустым.

Форма должна быть отправлена методом POST .

У Django есть подходящие поля модели для обработки загруженных файлов: FileField и ImageField .

Файлы, загруженные в FileField или ImageField , хранятся не в базе данных, а в файловой системе.

FileField и ImageField создаются как строковое поле в базе данных (обычно VARCHAR), содержащее ссылку на фактический файл.

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

Аргумент request.FILES является словарным объектом. Каждый ключ в request.FILES - это имя из <input type="file" name="" /> .

Каждое значение в request.FILES является экземпляром UploadedFile .

Вам нужно будет установить MEDIA_URL и MEDIA_ROOT в файле settings.py вашего проекта.

На сервере разработки вы можете обслуживать загруженные пользователем файлы (мультимедиа), используя представление django.contrib.staticfiles.views.serve() .

Чтобы получить доступ к MEDIA_URL в шаблоне, вы должны добавить django.template.context_processors.media к вашим context_processors в конфигурации TEMPLATES .

Простая загрузка файла

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

simple_upload.html

views.py

Загрузка файла с модельными формами

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

models.py

forms.py

views.py

model_form_upload.html

О параметре FileField upload_to

Смотрите пример ниже:

Обратите внимание на параметр upload_to . Файлы будут автоматически загружены в MEDIA_ROOT/documents/ .

Также возможно сделать что-то вроде:

Загруженный сегодня файл будет загружен в MEDIA_ROOT/documents/2019/08/01/ .

upload_to также может быть вызываемым параметром, который возвращает строку. Этот вызываемый параметр принимает два параметра, экземпляр (instance) и имя файла (filename).

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

Если вы принимаете загруженный контент от ненадежных пользователей, это создает угрозу безопасности! См. Тему руководства по безопасности на: ref: user-uploaded-content-security для подробностей по смягчению последствий.

Основы загрузки файлов¶

Рассмотрим простую форму, содержащую FileField :

Представление, обрабатывающее эту форму, получит данные файла в request.FILES , который представляет собой словарь, содержащий ключ для каждого FileField (или ImageField , или другой FileField ) в форме. Таким образом, данные из приведенной выше формы будут доступны как request.FILES['file'] .

Обратите внимание, что request.FILES будет содержать данные только в том случае, если метод запроса был POST , а <form> , отправивший запрос, имеет атрибут enctype="multipart/form-data"`. В противном случае ``request.FILES будет пустым.

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

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

Вот обычный способ обработки загруженного файла:

Есть несколько других методов и атрибутов, доступных для объектов UploadedFile ; смотрите UploadedFile для полной справки.

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

Если вы сохраняете файл в Model с FileField , используя ModelForm значительно упрощает этот процесс. Объект файла будет сохранен в расположение, указанное аргументом upload_to соответствующего FileField при вызове form.save() :

Если вы создаете объект вручную, вы можете просто назначить файловый объект из request.FILES полю файла в модели:

Загрузка нескольких файлов в Django¶

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

Затем переопределите метод post вашего подкласса FormView для обработки нескольких загрузок файлов:

Обработчики загрузки¶

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

Вместе MemoryFileUploadHandler и TemporaryFileUploadHandler обеспечивают стандартное поведение загрузки файлов Django для чтения небольших файлов в память и больших файлов на диск.

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

Где хранятся загруженные данные¶

Перед сохранением загруженных файлов данные необходимо где-то сохранить.

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

Однако, если загруженный файл слишком велик, Django запишет загруженный файл во временный файл, хранящийся во временном каталоге вашей системы. На Unix-подобной платформе это означает, что вы можете ожидать, что Django сгенерирует файл с именем что-то вроде /tmp/tmpzfp6I6.upload . Если загрузка достаточно велика, вы можете наблюдать, как этот файл увеличивается в размере, когда Django передает данные на диск.

Эти особенности - 2,5 мегабайта; /tmp ; и т.д. - это просто «разумные значения по умолчанию», которые можно настроить, как описано в следующем разделе.

Изменение поведения обработчика загрузки¶

Есть несколько настроек, которые управляют поведением загрузки файлов Django. Смотрите Настройки загрузки файла для подробностей.

Изменение обработчиков загрузки на лету¶

Иногда определенные представления требуют другого поведения загрузки. В этих случаях вы можете переопределить обработчики загрузки для каждого запроса, изменив request.upload_handlers . По умолчанию этот список будет содержать обработчики загрузки, заданные параметром FILE_UPLOAD_HANDLERS , но вы можете изменить список так же, как любой другой список.

Например, предположим, что вы написали ProgressBarUploadHandler , который обеспечивает обратную связь о ходе загрузки в какой-то виджет AJAX. Вы можете добавить этот обработчик в свои обработчики загрузки следующим образом:

Вы, вероятно, захотите использовать в этом случае list.insert() (вместо append() ), потому что обработчик индикатора выполнения должен будет запускаться перед любыми другими обработчиками. Помните, что обработчики загрузки обрабатываются по порядку.

Если вы хотите полностью заменить обработчики загрузки, вы можете просто назначить новый список:

Вы можете изменять обработчики загрузки только перед доступом к request.POST или request.FILES - нет смысла изменять обработчики загрузки после того, как обработка загрузки уже началась. Если вы попытаетесь изменить request.upload_handlers после чтения из request.POST или request.FILES , Django выдаст ошибку.

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

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