eFusion 26 мая 2020

Безопасная загрузка изображений в веб-приложении на Django

🖼️ 💾 Почти в любом веб-приложении есть необходимость принимать от пользователей картинки. В Django это можно делать лаконично и безопасно, используя ImageField и Pillow.
2
10494

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

В Django есть два поля, позволяющих загружать картинки: FileField и ImageField. Второй вариант – специализированная версия FileField, использующая подтверждение от библиотеки Pillow, что файл является изображением.

Начнем с создания моделей. Создадим файл models.py и поместим в него следующее содержимое:

models.py
        from django.db import models

class Image(models.Model):
    title = models.CharField(max_length=200)
    image = models.ImageField(upload_to='images')

    def __str__(self):
        return self.title
    

Переменная image – это поле ImageField, которое работает с API хранилища, который обеспечивает способ хранения/извлечения, а также чтения/записи файлов.

Параметр upload_to указывает путь, где будут храниться изображения. Для этой модели он будет соответствовать MEDIA_ROOT/images/

Также возможна установка динамических путей для изображений:

        image = models.ImageField(upload_to='users/%Y/%m/%d/', blank=True)
    

Это позволит хранить изображения в каталогах вида MEDIA_ROOT/users/2020/05/26.

Установим Pillow, выполнив следующую команду:

        pip install Pillow
    

Чтобы Django обслуживал медиафайлы, загруженные пользователями, добавим следующие настройки в файл settings.py вашего проекта:

        # Основной url для управления медиафайлами
MEDIA_URL = '/media/'

# Путь хранения картинок
MEDIA_ROOT = os.path.join(BASE_DIR, 'media/')
    

MEDIA_URL – это URL-адрес, который будет обслуживать медиафайлы, а MEDIA_ROOT – это путь к корневому каталогу, в котором хранятся файлы.

Добавим следующий код в urls.py:

urls.py
        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)
    

Теперь нам нужно создать форму для модели изображения. В файл forms.py добавим следующий код:

forms.py
        from django import forms
from .models import Image


class ImageForm(forms.ModelForm):
    class Meta:
        model = Image
        fields = ('title', 'image')
    

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

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

{% if img_obj %}
  <h3>Succesfully uploaded : {{img_obj.title}}</h3>
  <img src="{{ img_obj.image.url}}" alt="connect" style="max-height:300px">
{% endif %}
    

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

Напишем обработчик формы в views.py:

        from django.shortcuts import render
from .forms import ImageForm


def image_upload_view(request):
    """Process images uploaded by users"""
    if request.method == 'POST':
        form = ImageForm(request.POST, request.FILES)
        if form.is_valid():
            form.save()
            # Get the current instance object to display in the template
            img_obj = form.instance
            return render(request, 'index.html', {'form': form, 'img_obj': img_obj})
    else:
        form = ImageForm()
    return render(request, 'index.html', {'form': form})
    

Django делает всю работу сам, а мы просто прогоняем форму через валидацию и сохраняем ее при успешной загрузке файла. Теперь, когда обработчик готов, сопоставим все с URL-адресом в urls.py:

        urlpatterns = [
    ......
    path('upload/', views.image_upload_view)
    ......
]
    

Сохраним файлы, запустим сервер и проверим работу программы.

Заключение

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

Источники

РУБРИКИ В СТАТЬЕ

МЕРОПРИЯТИЯ

Комментарии 2

ВАКАНСИИ

Senior Backend Developer (Кипр)
от 3000 EUR до 4000 EUR
Программист С++
Санкт-Петербург, по итогам собеседования
Senior iOS Developer
Москва, от 250000 RUB до 300000 RUB

ЛУЧШИЕ СТАТЬИ ПО ТЕМЕ

BUG