Загрузка файлов в Django

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

Установка Django в Python 3

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

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

Давайте активируем новую виртуальную среду. 

Shell

$ cd ~/Desktop

$ mkdir insta && cd insta

$ pipenv install django==2.1.5 pillow==5.4.1

$ pipenv shell

(insta) $

О том, что виртуальная среда была активирована, сообщит изменение в (insta). Также можно в любое время указать команду exit, чтобы осуществить выход, а также pipenv shell, чтобы осуществить повторный вход.

Создание проекта и приложения в Django

Создадим проект. Дадим ему имя insta_project. А приложение назовем posts

Shell

(insta) $ django-admin startproject insta_project .

(insta) $ python manage.py startapp posts

Поскольку нами было добавлено новое приложение, нам обязательно необходимо уведомить об этом Django. Делается это через нижнюю часть конфигурации INSTALLED_APPS в settings.py

# insta_project/settings.py

INSTALLED_APPS = [

    'django.contrib.admin',

    'django.contrib.auth',

    'django.contrib.contenttypes',

    'django.contrib.sessions',

    'django.contrib.messages',

    'django.contrib.staticfiles',

    'posts.apps.PostsConfig', # новое

]

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

(insta) $ python manage.py migrate

Operations to perform:

  Apply all migrations: admin, auth, contenttypes, sessions

Running migrations:

  Applying contenttypes.0001_initial... OK

  Applying auth.0001_initial... OK

  Applying admin.0001_initial... OK

  Applying admin.0002_logentry_remove_auto_add... OK

  Applying admin.0003_logentry_add_action_flag_choices... OK

  Applying contenttypes.0002_remove_content_type_name... OK

  Applying auth.0002_alter_permission_name_max_length... OK

  Applying auth.0003_alter_user_email_max_length... OK

  Applying auth.0004_alter_user_username_opts... OK

  Applying auth.0005_alter_user_last_login_null... OK

  Applying auth.0006_require_contenttypes_0002... OK

  Applying auth.0007_alter_validators_add_error_messages... OK

  Applying auth.0008_alter_user_username_max_length... OK

  Applying auth.0009_alter_user_last_name_max_length... OK

  Applying sessions.0001_initial... OK

Создаем модели Django

Рекомендуется начинать с модели базы данных. В нашем примере у модели Post будет лишь два поля: title и cover. Далее нами также будет добавлена функция __str__(), чтобы title показался в интерфейсе администратора Django. 

# posts/models.py

from django.db import models

 

 

class Post(models.Model):

    title = models.TextField()

    cover = models.ImageField(upload_to='images/')

 

    def __str__(self):

        return self.title

Расположение загружаемых файлов image будет в MEDIA_ROOT/imanges. В Django локацией для MEDIA_ROOT, по умолчанию является каталог, откуда все файлы пользователя и будут открываться.

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

Настройка MEDIA_ROOT

Откройте insta_project/settings.py в текстовом редакторе. Нам понадобится добавить две новые конфигурации. По умолчанию MEDIA_URL и MEDIA_ROOT являются пустыми и не показываются. Поэтому требуется предварительная настройка.

  1. MEDIA_ROOT является путем файловой системы, куда пользователи будут загружать файлы.
  2. MEDIA_URL являет собой адрес сайта, который будет использоваться в файловых шаблонах.
Python

# insta_project/settings.py

MEDIA_URL = '/media/'

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

 

Название media не нужно в обязательном порядке использовать. Можно выбрать любое другие имя. Но можно остановиться и на этом, поскольку оно используется по умолчанию в Django. Также нами будет создана папка images внутри, чтобы навигация стала проще. 

(insta) $ mkdir media

(insta) $ mkdir media/images

Панель администратора (админ-панель) в Django

Теперь мы обновим файл posts/admin.py. После этого в Django появится возможность использовать приложение Post с правами администратора. 

# posts/admin.py

from django.contrib import admin

 

from .models import Post

 

admin.site.register(Post)

На этом этапе у нас все получилось настроить. Теперь надо сгенерировать файл миграции.  

(insta) $ python manage.py makemigrations

Migrations for 'posts':

  posts/migrations/0001_initial.py

    - Create model Post

Теперь запускаем migrate. Это делается для апгрейда базы данных. 

(insta) $ python manage.py migrate

Operations to perform:

  Apply all migrations: admin, auth, contenttypes, posts, session

s

Running migrations:

  Applying posts.0001_initial... OK

Теперь мы можем создать аккаунт superuser, через который и будет получаться доступ к интерфейсу администратора. А затем выполнить runserver для первого запуска локального веб-сервера. 

(insta) $ python manage.py createsuperuser

(insta) $ python manage.py runserver

Если набрать в адресной строке http://127.0.0.1:8000/admin, то можно будет зайти в админ-панель. Страница будет выглядеть следующим образом.

Далее найдите Posts и нажмите кнопку +. Здесь добавляется все, что пожелаете. Тем не менее, в данном руководстве мы создаем запись с изображением талисмана Django – пони.Загрузка файлов в Django

После клика по кнопке «Save» пользователь будет перенаправлен на страницу «Posts», на которой размещены все записи, которые есть.Загрузка файлов в Django

Теперь если вы откроете каталог media в проекте, то обнаружите, что в папке images появилась картинка djangopony.png. Как и было оговорено прежде, MEDIA_URL необходим как раз для этого.

Итак, с основами мы разобрались. Теперь попробуем понять то, как отображать записи, использовать urls.py, views.py, а также шаблоны файлов.

Настройка urls.py в Django

Аспектом работы с Django, который может несколько запутать, является тот факт, что зачастую для одной страницы потребуется четыре файла. Это models.py, urls.py, views.py, а также htmlшаблоны. 

Здесь мы будем разбирать понятия в такой последовательности: models, urls, views, templates. Поскольку модель уже мы разобрали ранее, давайте теперь рассмотрим URL. 

Нам потребуется выполнить апгрейд файла urls.py. Сперва на проектном уровне insta_project/urls.py необходимо добавить импорты для settings, include и static.

Затем нам необходимо определить путь для приложения posts. Необходимо отметить, что если настройки в режиме DEBUG, то MEDIA_URL также требуется добавить. Иначе не получится увидеть картинки, которые загружаются. 

# insta_project/urls.py

from django.contrib import admin

from django.conf import settings # new

from django.urls import path, include # new

from django.conf.urls.static import static # new

 

urlpatterns = [

    path('admin/', admin.site.urls),

    path('', include('posts.urls')), # new

]

 

if settings.DEBUG: # new

    urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

Затем надо рассортировать пути URL в рамках приложения posts. Сначала необходимо создать файл через linux команду touch

(insta) $ touch posts/urls.py

Это будет связано с представлением HomePageView, созданием которого мы займемся далее.

Представления в Django

Здесь также можно воспользоваться стандартным ListView, основанном на классе, после чего выполнить импорт модели Post. Затем создается HomePageView, что использует эту модель. Также надо сгенерировать шаблон, называющийся home.html

# posts/views.py

from django.views.generic import ListView

from .models import Post





class HomePageView(ListView):

    model = Post

    template_name = 'home.html'

Затем переходим к файлу-шаблону, который называется home.html.

Шаблоны templates в Django

Есть два способа, какими выбирается локация для шаблона. Можно было бы его разместить в posts, который находится по адресу posts/templates/posts/home.html. Правда, тогда структура станет избыточной. Помимо этого, если шаблоны находятся глубоко в папках приложений, то их разбор будет сопряжен с дополнительными трудностями. 

Как раз поэтому для урока на проектном уровне нами будет создана отдельная папка templates

$ mkdir templates

$ touch templates/home.html

Затем дадим Django команду, чтобы эта директория также рассматривалась в процессе поиска шаблонов. Для этого необходимо внести изменения в конфигурацию TEMPLATES в insta_project/settings.py.  

Python

# insta_project/settings.py

TEMPLATES = [

    {

        ...

        'DIRS': [os.path.join(BASE_DIR, 'templates')], # new

        ...

    },

]

На этом все. Далее запустите сервер и перейдите на домашнюю страницу http://127.0.0.1:8000. Если в том будет необходимость, перезапустите страницу.Загрузка файлов в Django

Ура! Если вы добавите дополнительные посты с заголовками и картинками от лица администратора, то они добавятся на главную.

Форма для добавления записи

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

Сперва начнем с файла views.py. Новое представление будет называться CreatePostView. Оно расширит CreateView, которое является компонентом Django. Также выполним импорт reverse_lazy, отвечающий за возвращение на домашнюю страницу после отправки формы с помощью POST-запроса.

В представлении мы приводим model, form_class, который будет сгенерирован далее, template_name и, естественно, success_url, полученный после отправки. 

# posts/views.py

from django.views.generic import ListView, CreateView # новый

from django.urls import reverse_lazy # новый

 

from .forms import PostForm # новый

from .models import Post

 

class HomePageView(ListView):

    model = Post

    template_name = 'home.html'

 

class CreatePostView(CreateView): # новый

    model = Post

    form_class = PostForm

    template_name = 'post.html'

    success_url = reverse_lazy('home')

А теперь давайте попробуем создать форму. Чтобы это сделать, введите следующую команду. 

(insta) $ touch posts/forms.py

Также возможно расширение ModelForm, который является компонентом Django. В нашем случае у базовой формы необходимо уточнить правильную модель Post и названия полей, которые выводятся на экран. В нашем примере это title и cover

# posts/forms.py

from django import forms

from .models import Post

 

class PostForm(forms.ModelForm):

 

    class Meta:

        model = Post

        fields = ['title', 'cover']

Для формы генерируется специальная страница, которая будет иметь URL-путь post/

# posts/urls.py

from django.urls import path

 

from .views import HomePageView, CreatePostView # new

 

urlpatterns = [

    path('', HomePageView.as_view(), name='home'),

    path('post/', CreatePostView.as_view(), name='add_post') # new

]

Затем генерируем шаблон. 

(insta) $ touch templates/post.html

Затем туда вносим заголовок и форму. В целях защиты рекомендуется всегда добавлять csrf_token. Уточняем form.as_p, из-за чего Django каждое поле будет выводить в виде отдельного параграфа. 

<!-- templates/post.html -->

<h1>Create Post Page</h1>

<form method="post" enctype="multipart/form-data">

  {% csrf_token %}

  {{ form.as_p }}

  <button type="submit">Submit New Post</button>

</form>

Вот и результат. Удостоверьтесь, что сервер запущен, и перейдите на страницу http://127.0.0.1:8000/post/.Загрузка файлов в Django

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

Что дальше?

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

Для размещения файлов лучше не использовать Django. Лучше настроить отдельную внешнюю службу, например, сеть доставки контента Content Delivery Network (CDN).

ОфисГуру
Adblock
detector