Сайт на Django за 20 минут

Современные веб-сайты, требующие сложного взаимодействия с пользователем, создаются с использованием специальных фронтенд-фреймворков, таких как React, Vue.js и другие. Каждый из них имеет свои плюсы и минусы. Вам приходится учитывать скорость разработки с применением выбранного фреймворка, стоимость хостинга, SEO-оптимизацию, различия в синтаксисе и, в некоторых случаях, дублирование бизнес-логики.

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

В этой статье мы вам расскажем, как за 20 минут создать несложный сайт на Django.

Реализовать необходимые нам функции можно при помощи нескольких технологий (на выбор). Например, можно воспользоваться Sockpuppet, Reaction или Unicorn. Для обеспечения интерактивности приложения без применения пользовательского JavaScript мы применим Unicorn.

Прежде чем начать

Чтобы следовать этому руководству, вам необходимо:

Настройка и обзор проекта

Вот краткий обзор приложения, которое мы будем сейчас создавать:

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

Для начала клонируйте ветку base из репозитория django-reactive:

$ git clone https://github.com/Samuel-2626/django-reactive --branch base --single-branch
$ cd django-reactive

Мы будем использовать Docker, чтобы упростить настройку и запуск Django с зависимостями. Из корня проекта создайте образы и раскрутите контейнеры Docker:

$ docker-compose up -d --build

Затем примените миграции, создайте суперпользователя и запустите сервер разработки:

$ docker-compose exec web python manage.py migrate
$ docker-compose exec web python manage.py createsuperuser
$ docker-compose exec web python manage.py run server

Обратите внимание на модель Book в файле books/models.py. Код должен выглядеть следующим образом:

from django.db import models
class Book(models.Model):
    title = models.CharField(max_length=200)
    def __str__(self):
        return self.title
[django_ad_block]

Работа с Unicorn

Unicorn – это компонентный фреймворк, прогрессивно улучшающий стандартное представление Django. Он динамически обновляет DOM с помощью вызовов AJAX в фоновом режиме.

Добавьте Unicorn к вашим установленным приложениям:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    # Third-party
    "django_unicorn", # new
]

Далее обновите файл urls.py вашего проекта следующим образом:

from django.urls import path, include
path("unicorn/", include("django_unicorn.urls")), # new

Как это работает?

  1. Unicorn – это библиотека с открытым исходным кодом, улучшающая стандартное представление Django. Благодаря этому первоначальная визуализация компонента выполняется быстро и отлично подходит для SEO.
  2. Затем Unicorn привязывается к указанным элементам и при необходимости автоматически выполняет вызовы AJAX.
  3. Наконец, Unicorn динамически обновляет DOM.

URL проекта, views и template

В этом разделе мы будем настраивать URL-адреса, вьюшки (views) и шаблоны (template) нашего проекта.

Для начала обновите файл urls.py следующим образом:

path("", views.index), # new

Далее обновите файл views.py, добавив в него следующий код:

def index(request):
    return render(request, "index.html", {})

Наконец, обновите файл index.html:

{% load unicorn %}

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>Django Books</title>

    <link
      href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css"
      rel="stylesheet"
      integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC"
      crossorigin="anonymous"
    />
    {% unicorn_scripts %}
  </head>
  <body>
    {% csrf_token %}
    <div class="container">
      <h2>Favourite Django Books</h2>

      {% unicorn 'book' %}
    </div>
  </body>
</html>

Логика работы

  1. Мы создали базовый шаблон Django для своего проекта, связав views и urls вместе.
  2. Обратите внимание, что Unicorn нужно загрузить в верхней части HTML-шаблона Django.
  3. Мы также добавили unicorn_scripts и crsf_token в шаблон Django HTML.

Как написано в документации Unicorn, библиотека следует лучшим практикам Django и, следовательно, требует установки CRSF-токена на любой странице, являющейся компонентом. Это гарантирует, что никакие некорректные сообщения AJAX не будут выполнены.

Также Unicorn имеет концепцию компонентов. Это позволяет обращаться к набору интерактивных функций, которые могут быть помещены в шаблон. Например, мы добавили компонент book в файл index.html.

Добавление и удаление книг

В этом разделе мы реализуем функцию добавления и удаления книг без обновления браузера с помощью Unicorn.

Шаг 1

В корне вашего проекта создайте новые папки (unicorn и components) и новый файл с именем book.py.

Шаг 2

В папке unicorn, которую вы создали ранее, создайте еще одну папку с именем templates, внутри нее — папку с именем unicorn и, наконец, внутри этой папки создайте файл с именем book.html. (У вас должен получиться путь unicorn/templates/unicorn/book.html).

Шаг 3

Внутрь book.html добавьте следующий код:

<div class="row">
  <div class="col-md-6">
    <section>
      <ul class="list-group">
        {% for book in books %}
        <li class="list-group-item">
          {{ book.title }}
          <button
            class="btn btn-outline-danger"
            style="float: right;"
            unicorn:click="delete_book('{{ book.id }}')"
          >
            Delete Book
          </button>
        </li>
        {% empty %}
        <p>Database Empty | Add your favourite Django book</p>
        {% endfor %}
      </ul>
    </section>
  </div>
  <div class="col-md-6">
    <form>
      <input
        type="text"
        class="form-control"
        placeholder="Enter title of the book..."
        unicorn:model.defer="title"
      />
      <br />
      <button
        class="btn btn-secondary"
        style="min-width: 100%;"
        unicorn:click.prevent="add_book"
      >
        Add Books
      </button>
    </form>
  </div>
</div>

Что здесь происходит?

Внутри компонента у нас есть доступ к обычному синтаксису Django.

Обратите внимание на элемент input. Всё знакомо, за исключением атрибута unicorn: model. Он указывает, какое поле в вашем внутреннем компоненте будет привязано к этому вводу. В этом случае имя поля будет title.

Примечание. unicorn: model – это магия, которая связывает входные данные с компонентом бэкенда.

Обратите внимание на кнопку «Add Books» с атрибутом unicorn:click. Этот атрибут указывает Unicorn привязать бэкенд-метод add_book к событию браузера click.

Точно так же кнопка «Delete Book» указывает Unicorn привязать бэкенд-метод delete_book. Кроме того, мы также передали идентификатор книги в функцию delete_book, чтобы однозначно идентифицировать каждую книгу.

Чтобы предотвратить появление обновлений при каждом входе, вы можете добавить модификатор lazy или defer в конец unicorn:model.

Атрибуты, используемые в шаблонах компонентов, обычно начинаются с unicorn:, но также поддерживается шорткат u:. Обратите внимание, что свойства компонента могут быть многих типов, включая str, int, list, dictionary, decimal и Django Model.

Наконец, Unicorn требуется один корневой элемент, охватывающий весь шаблон компонента.

Шаг 4

Внутри book.py добавьте следующий код:

from django_unicorn.components import UnicornView
from books.models import Book
class BookView(UnicornView):
    title: str = ""
    books = Book.objects.none()
    def hydrate(self):
        self.books = Book.objects.all()
    def add_book(self):
        if self.title != "":
            book = Book(title=self.title)
            book.save()
        self.title = ""
    def delete_book(self, id):
        try:
            book = Book.objects.get(id=id)
            book.delete()
        except:
            pass

Объяснение логики кода

  1. Мы импортируем UnicornView, внутренний подкласс TemplateView. Следовательно, процесс перехода от стандартного view на основе классов должен быть простым.
  2. При создании экземпляра компонента для получения последних книг из базы данных вызывается метод hydrate. Таким образом поддерживается актуальность информации.
  3. Метод add_book создает новую модель book из title, сохраняет ее в базе данных, а затем очищает title.
  4. Метод delete_book удаляет книгу, соответствующую идентификатору.

Пройдя все описанные шаги, перейдите по адресу http://127.0.0.1:8080/, чтобы убедиться, что приложение работает должным образом. Вы должны увидеть следующее:

Попробуйте добавить или удалить свои любимые книги по Django.

Заключение

Мы разобрали, как создать сайт на Django за 20 минут. Мы создали реактивное веб-приложение с полным стеком на Django, без какого-либо JavaScript. Также мы использовали Unicorn, чтобы иметь возможность добавлять и удалять книги, не обновляя страницу.

Вы можете скачать полный код здесь.

Успехов в написании кода!

Перевод статьи «Full-Stack Reactive Website in Django (No JavaScript)».