Створюємо форму завантаження файлів в Django

  • 3 апреля, 14:27
  • 5150
  • 0

У цьому посібнику показано, як реалізувати завантаження файлів з Django. Для цього створимо простий клон Instagram, який буде працювати з зображеннями.

Створюємо форму завантаження файлів в Django

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

Для простоти папку з навчальним прикладом краще помістити на робочому столі, але в загальному і цілому розташування особливого значення не має. Головне, щоб директорія проекту була легко доступною.

Відкрийте командний рядок і створіть директорію  insta для зберігання файлів. Для установки як Django, так і Pillow ми будемо використовувати Pipenv. Pillow є бібліотекою для обробки зображень. Для завантаження інші типів файлів Pillow не знадобиться.

Активуємо нове віртуальне середовище:

$ cd ~/Desktop
$ mkdir insta && cd insta
$ pipenv install django==2.1.5 pillow==5.4.1
$ pipenv shell
(insta) $

Про  активацію віртуального середовища  повідомить зміна в  (insta). Ви також можете в будь-який час ввести команду  exit для виходу і  pipenv shell для повторного входу.

Створення проекту і додатку в Django

Створимо  новий проект Django  під назвою  insta_project і новий додаток, який назвемо  posts.

(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.sesions' ,
    '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/images. В Django локацією для  MEDIA_ROOT за замовчуванням є папка, звідки будуть завантажуватися всі файли користувача.

У разі, коли замість зображення потрібно  завантажити інший файл , потрібно просто поміняти  ImageField на  FileField.

Налаштування MEDIA_ROOT в Django 2

Відкрийте  insta_project/settings.py в текстовому редакторі. Нам буде потрібно додати дві нові конфігурації. За замовчуванням  MEDIA_URL і  MEDIA_ROOT є порожніми і не відображаються на екрані, тому їх необхідно налаштувати:

  1. MEDIA_ROOT є шляхом файлової системи, куди користувачі будуть завантажувати файли;
  2. MEDIA_URL є URL, який ми можемо використовувати в шаблонах для файлів.

# insta_project/settings.py
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

Назву  media використовувати не обов'язково, можна вибрати будь-яку, просто в Django  media використовується за замовчуванням. Ми також  створюємо папку 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, з'явиться можливість  зайти в адмінку Django . Ви будете направлені на наступну сторінку:

Натисніть на  + Add біля  Posts. Тут можна додати все, що хочете, але в цьому посібнику ми створюємо запис із зображенням талісмана Django - поні.

Після натискання « Save » ви будете перенаправлені на сторінку  Posts, де розташовані всі наявні записи.

Тепер якщо ви загляньте в папку  media в вашому проекті, то побачите, що в директорії  images з'явилося зображення  djangopony.png. Як і було сказано раніше,  MEDIA_URL потрібен саме для цього.

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

Налаштування urls.py в Django

Аспектом роботи з Django, який може дещо заплутати, є той факт, що найчастіше для однієї веб-сторінки потрібно 4 різних, але взаємопов'язаних файли:  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

Потім ми винесемо всі записи на головну сторінку, для цього використовуємо порожній рядок  ' ' в якості шляху.

# posts/urls.py
from django.urls import path

from .views import HomePageView

urlpatterns = [
    path('', HomePageView.as_view(), name='home'),
]

Це буде пов'язано з  view  HomePageView, створенням якого ми займемося далі.

views в 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.

# insta_project/settings.py
TEMPLATES = [
    {
        ...
        'DIRS': [os.path.join(BASE_DIR, 'templates')], # new
        ...
    },
]

Файл шаблону  home.html показує  title і  image всіх наших записів. У Instagram все було б так само.

<!-- templates/home.html -->
<h1>Django Image Uploading</h1>
<ul>
  {% for post in object_list %}
    <h2>{{ post.title }}</h2>
    <img src="{{ post.cover.url}}" alt="{{ post.title }}">
  {% endfor %}
</ul>

От і все. Запустіть сервер командою  python manage.py runserver і перейдіть на домашню сторінку  http://127.0.0.1:8000. У разі необхідності перезавантажте сторінку.

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

Форма для додавання запису в Django

Тепер ми можемо створити html форму для того, щоб звичайні користувачі без доступу в адмінку могли також додавати записи і завантажувати файли. Це передбачає створення нової сторінки за допомогою форми.

Давайте почнемо з файлу views.py. Назвемо нове уявлення CreatePostView. Воно розширить вбудоване в Django CreateView. Також імпортуємо 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

Ми можемо розширити вбудований в Django ModelForm. Тут у базовій формі потрібно уточнити правильну модель 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/.

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

Наступні кроки

І що тепер? Багатьом напевно захочеться накласти певні обмеження на розмір картинки. Це можна зробити в файлі  models.py або за допомогою CSS. Також багатьом напевно захочеться додати опції редагування або видалення для записів.

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

По матеріалам: python-scripts.com


0 комментариев
Сортировка:
Добавить комментарий

IT Новости

Смотреть все