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

На большинстве веб-сайтов мы часто имеем дело с мультимедийными данными, такими как изображения, файлы и т. д. В django мы можем работать с изображениями с помощью поля модели ImageField.

В этой статье мы создали приложение image_app в тестовом проекте с названием image_upload.

Первым делом добавим в файл settings.py приведенный ниже код .

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

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

В файле urls.py мы должны отредактировать конфигурацию следующим образом

from django.conf import settings
from django.conf.urls.static import static
if settings.DEBUG:
        urlpatterns += static(settings.MEDIA_URL,
                              document_root=settings.MEDIA_ROOT)

Пример models.py должен быть таким, поскольку мы создали модель Hotel, в которой определили поля для названия отеля и его изображения.

# models.py
 class Hotel(models.Model):
    name = models.CharField(max_length=50)
    hotel_Main_Img = models.ImageField(upload_to='images/')

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

Мы должны создать файл forms.py для модели нашей формы

# forms.py
from django import forms
from .models import *
  
class HotelForm(forms.ModelForm):
  
    class Meta:
        model = Hotel
        fields = ['name', 'hotel_Main_Img']

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

Теперь создадим каталог шаблонов,image_app в котором мы должны создать html-файл для загрузки изображений. HTML-файл должен выглядеть так.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Hotel_image</title>
</head>
<body>
    <form method = "post" enctype="multipart/form-data">
        {% csrf_token %}
        {{ form.as_p }}
        <button type="submit">Upload</button>
    </form>
</body>
</html>

При выполнении запроса POST мы должны каким-то образом кодировать данные, которые образуют тело запроса. Итак, нам нужно указать формат кодирования в теге формы. multipart/form-dataзначительно сложнее, но позволяет включать в данные целые файлы.

csrf_token предназначен для защиты от подделки межсайтовых запросов.

form.as_p просто оборачивает все элементы в теги абзаца HTML. Преимущество заключается в отсутствии необходимости писать цикл в шаблоне для явного добавления HTML для окружения каждого заголовка и поля.

В views.py добавим код представления чтобы принять запрос от пользователя и вернуть некоторую HTML - страницу.

from django.http import HttpResponse
from django.shortcuts import render, redirect
from .forms import *
  
# Create your views here.
def hotel_image_view(request):
  
    if request.method == 'POST':
        form = HotelForm(request.POST, request.FILES)
  
        if form.is_valid():
            form.save()
            return redirect('success')
    else:
        form = HotelForm()
    return render(request, 'hotel_image_form.html', {'form' : form})
  
  
def success(request):
    return HttpResponse('successfully uploaded')

всякий раз, когда происходит обращение к hotel_image_view с помощью POST-запроса, мы создаем экземпляр модели, form = HotelForm(request.POST, request.FILES) изображение формы будет храниться в request.FILES. Если он действителен, сохраним в базе данных и перенаправим на URL-адрес, который указывает на успешную загрузку изображения. Если метод не POST, мы выполняем рендеринг с созданным шаблоном html.

urls.py будет выглядеть так -

from django.contrib import admin
from django.urls import path
from django.conf import settings
from django.conf.urls.static import static
from .views import *
  
urlpatterns = [
    path('image_upload', hotel_image_view, name = 'image_upload'),
    path('success', success, name = 'success'),
]
  
if settings.DEBUG:
        urlpatterns += static(settings.MEDIA_URL,
                              document_root=settings.MEDIA_ROOT)

Теперь создадим миграции и запустим dev-сервер.

Когда мы нажимаем URL-адрес в браузере, он выглядит вот так.

После загрузки изображение будет успешным.

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

Окончательный результат сохраняется в базе данных

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

# Python program to view 
# for displaying images
  
def display_hotel_images(request):
  
    if request.method == 'GET':
  
        # getting all the objects of hotel.
        Hotels = Hotel.objects.all() 
        return render((request, 'display_hotel_images.html',
                     {'hotel_images' : Hotels}))

Образец шаблона файла HTML для отображения изображений.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Hotel Images</title>
  
      <meta name="viewport" content="width=device-width, initial-scale=1">
      <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
      <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js">
      </script>
      <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js">
      </script>
</head>
<body>
  
    {% for hotel in hotel_images %}
            <div class="col-md-4">
                    {{ hotel.name }}
                     <img src="{{ hotel.hotel_Main_Img.url }}" class="img-responsive" style="width: 100%; float: left; margin-right: 10px;" />
            </div>
    {% endfor %}
  
</body>
</html>

Укажем путь в файле urls.py

# urls.py
path('hotel_images', display_hotel_images, name = 'hotel_images'),

Смотрим, что получилось

Изображение отеля