Как загружать файлы и изображения в приложении Django

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

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

Теперь выполните команду cd на этот каталог и сформируйте виртуальную среду: 

mkdir filesDjango
cd filesDjango
python3.8 -m venv env

Активируйте ее и туда же установите Django: 

source env/bin/activate

pip install Django

Создайте новый проект Django и назовите его file uploads:

django-admin startproject fileuploads

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

django-admin startapp files

Добавьте файлы приложения к списку установленного софта в файле settings.py:

INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'files',
]

Django сохраняет файлы локально с помощью параметров MEDIA_ROOT и MEDIA_URL.

 Определим эти константы в файле settings.py.:

import os

MEDIA_URL = "/media/"
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

MEDIA_ROOT будет использоваться для управления сохраненными данными, а MEDIA_URL  —  как url данных, которые требуется предоставить.

Загрузка данных 

Самый простой вариант  —  загружать файлы с помощью FileFields. Начните с создания простой модели в файле models.py, которая будет содержать три поля: имя, электронную почту и файл для загрузки.

from django.db import models

# Создайте модели здесь.

class Resume(models.Model):
    email = models.EmailField()
    name = models.CharField(max_length= 255, blank=False, null=False)
    file = models.FileField(upload_to= 'files/',null=True)

    def __repr__(self):
        return 'Resume(%s, %s)' % (self.name, self.file)

    def __str__ (self):
        return self.name

 Параметр upload_to указывает, куда будут перемещены файлы. 

Запуск миграций 

Миграции создадут актуальные таблицы в базе данных.

python3.8 manage.py migrate

Формы 

Django имеет встроенный класс ModelForm, позволяющий легко создавать формы из модельных полей. Создайте новый файл forms.py и добавьте код:

from django import forms
from .models import Resume

class ResumeForm(forms.ModelForm):

class Meta:
model = Resume
fields = ['email','name','file']

Определив форму, вы получите данные из нее с помощью request.FILES, используя запрос POST в представлении. Чтобы получить данные, содержащиеся в форме, откройте файл view.py и напишите следующий код:

from django.shortcuts import render
from django.http import HttpResponseRedirect
from .forms import ResumeForm

# Создайте здесь представления.

def upload_resume(request):
if request.method == 'POST':
form = ResumeForm(request.POST, request.FILES)
if form.is_valid():
form.save()
return HttpResponseRedirect("/")
else:
form = ResumeForm
return render(request, 'files/resume.html', {'form':form})

В вышеизложенном коде проверьте, чтобы метод запроса был POST, затем получите данные из формы, проверьте их и сохраните в базе данных. Если метод запроса  —  GET, то отобразите форму в шаблоне. 

Мы еще не создали шаблон upload.html (Django автоматически найдет его в соответствующем каталоге), с помощью которого будет отображена форма, так что давайте приступим. Создайте файлы, как показано ниже: 

templates/
files/
-upload.html

Для отправки формы в шаблон ей необходим атрибут enctype="multipart/form-data", иначе request.FILES вернется пустым: 

{% block content %}
<form method = "post", enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
<button type="submit"> Submit</button>
</form>
{% endblock %}

Тег csrf_token защитит форму от вредоносных данных, а form.as_p отобразит поля в виде параграфов. 

Регистрация путей URL

Сперва создайте файл urls.py, чтобы зарегистрировать URL для отображения формы, а затем  —  urls.py. Добавляем код: 

from django.urls import path
from .views import upload_resume


urlpatterns = [
path('upload_resume/',upload_resume, name = "files" )
]

Следующий шаг  —  регистрация файлов URL в корне url.py

from django.contrib import admin
from django.urls import path, include

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

Теперь, если вы запустите сервер и перейдете по адресу http://127.0.0.1:8000/upload_resume/, вы увидите формы, как изображено ниже: 

Django Admin

Django Admin  —  мощный интерфейс, который позволяет разработчикам добавлять данные в приложении. Зарегистрируем модель Resume в файле admin.py

from django.contrib import admin
from .models import Resume

# Зарегистрируйте вашу модель здесь.
admin.site.register(Resume)

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

Суперпользователь позволяет выполнять действия администратора: 

python3.8 manage.py createsuperuser
Username (leave blank to use 'earthtoast'):
Email address:
Password:
Password (again):
Superuser created successfully.

Когда вы перейдете по адресу http://127.0.0.1:8000/admin/ и войдете в систему под именем созданного суперпользователя, вы сможете просмотреть представленные данные. 

Как видите, ваш файл хранится в каталоге files.

Загрузка изображений в Django 

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

class Image(models.Model):
title = models.CharField(max_length= 255, blank=False, null=False)
image = models.ImageField(upload_to='images/', null=True, max_length=255)

def __repr__(self):
return 'Image(%s, %s)' % (self.title, self.image)

def __str__ (self):
return self.title

Для поля imageField, которое определено выше, необходима библиотека pillow, поэтому установите ее с помощью pip

pip install Pillow

Примените миграции, чтобы повлиять на изменения в моделях: 

python3.8 manage.py makemigrations files
Migrations for 'files':
files/migrations/0002_image.py
- Create model Image

Запустите команду migrate

python3.8 manage.py migrate 
Operations to perform:
Apply all migrations: admin, auth, contenttypes, files, sessions
Running migrations:
Applying files.0002_image... OK

Далее создайте форму по примеру Resume

from django import forms
from .models import Resume,Image

class ResumeForm(forms.ModelForm):

class Meta:
model = Resume
fields = ['email','name','file']

class ImageForm(forms.ModelForm):

class Meta:
model = Image
fields = ['title','image']

Для отображения изображения в форме необходимо представление. В файл views.py добавьте код: 

def upload_images(request):
if request.method == 'POST':
form = ImageForm(request.POST, request.FILES)
if form.is_valid():
form.save()
return HttpResponseRedirect("/")
else:
form = ImageForm

return render(request, 'files/images.html', {'form':form})

Создайте файл image.html в папке templates и пропишите в нем следующее: 

{% block content %}
<form method = "post", enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
<button type="submit"> Submit</button>
</form>

Теперь подключите представление upload_image к URL, открывайте urls.py и прописывайте: 

from django.urls import path
from .views import upload_resume,upload_images

urlpatterns = [
    path('upload_resume/',upload_resume, name = "files" ),
     path('upload_images/',upload_images, name = "images" ),
]

Форму загрузки изображения можно найти по адресу http://127.0.0.1:8000/upload_images/.

Предоставление файлов 

Первым делом добавьте django.template.context_processors.media в опцию context_processors в TEMPLATES в файле settings.py. Это позволит использовать {{ MEDIA_URL }} в шаблоне: 

TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.media',
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]

Далее обновите представление, чтобы выбрать изображения из базы данных: 

from django.shortcuts import render
from .models import Image

def upload_images(request):
    if request.method == 'GET':
        images = Image.objects.order_by('title')
        return render(request, "files/images.html", {"images": images })

Обновите шаблон image.html для отображения картинок:

{% for image in images %}
<div>
{{ image.title }}
</div>
<div>
<img src="{{ image.image.url }}" >
</div>
{% endfor %}

Вы можете предоставлять загруженные файлы из медиамаршрута в процессе работы, используя представление django.views.static.serve()

Добавьте следующий путь в корень URL-файла: 

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

urlpatterns = [
path('admin/', admin.site.urls),
path('',include('files.urls'))
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

Теперь при переходе по адресу http://127.0.0.1:8000/upload_images/ ваши изображения будут выводиться на экран. 

Заключение 

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

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

Читайте нас в TelegramVK и Яндекс.Дзен


Перевод статьи Esther Vaati: How to Upload Files and Images in Your Django Application

Предыдущая статьяКак создать пользовательскую поисковую панель SwiftUI с LazyVStack 
Следующая статьяОбзор команд Git для отмены изменений