Как создать блог на Django с опросами и тестами. Часть 1

Как создать блог на Django с опросами и тестами. Часть 1

Рассказываем, как создать многофункциональную социальную платформу и развернуть готовое приложение на сервере.

Введение

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

Исходный код проекта находится в репозитории. Делайте форк и предлагайте свои улучшения!

Структура и функциональность проекта

На этапе проектирования важно разбить проект на самостоятельные приложения. Базово в блоге есть сервисы для аутентификации и авторизации, управления записями, опросами и тестами. Итого четыре приложения: 

  • users — аутентификация, авторизация, создание и редактирование профилей. Подписка на блоги, мессенджер, обработка контактной формы, поиск пользователей по интересам и ключевым словам.  
  • blog — создание, редактирование и удаление записей. Лайки, закладки, рекомендации, комментарии, сортировка записей по категориям и тегам. Поиск по ключевым словам в записях пользователей.
  • polls — проведение опросов и голосований. Визуализация реализована с помощью библиотеки Chart.js.
  • quizzes — модуль для создания и проведения тестов. Поддерживаются два типа вопросов — с единственным правильным и несколькими ответами.

Инициализируем проект

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

python -m venv blogit\venv
cd blogit
venv\scripts\activate

Установить зависимости можно с помощью requirements.txt — он содержит список необходимых модулей. Файл доступен по ссылке.

pip install -r requirements.txt

Вместе со всеми модулями pip подтягивает основной — django. Теперь можно создать проект.

django-admin startproject config .

Точка в конце команды нужна, чтобы директория проекта config и управляющий скрипт manage.py находились на одном уровне с директориями приложений.

Каждое приложение будет содержать внутри своей директории набор html-шаблонов, которые будет возвращать Django в ответ на сетевые запросы. Но также есть несколько базовых и универсальных шаблонов, к которым должны иметь доступ все приложения — они расположены в папке templates внутри корневой директории проекта: 

  • base.html — базовый шаблон проекта, в котором подключаются статические файлы, иконки и внешние скрипты.
  • delete_template.html — удаление объектов (записей, интересов и так далее).
  • landing.html — главная страница платформы, которая видна только неавторизованным пользователям.
  • navbar.html — меню с разделами сайта.
  • pagination.html — универсальный шаблон для постраничного вывода любых объектов – от профилей и записей до опросов и тестов.
  • socials.html — ссылки на аккаунты в соцсетях.

Приложение users

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

manage.py startapp users

Также важно зарегистрировать новое приложение в корневой директории проекта, в конфигурационном файле settings.py.

/config/settings.py

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

path('', include('users.urls')),

Собственные маршруты приложения users будут храниться в файле users/urls.py — их можно найти и модифицировать по ссылке.

Шаблоны users расположены в отдельной директории — users/templates/users:

  • account.html — загружает собственный профиль авторизованного пользователя для редактирования.
  • friends.html — выводит карточки с профилями друзей пользователя.
  • inbox.html — страница с входящими сообщениями.
  • message.html — вывод текста полученного сообщения.
  • profile_form.html — форма для добавления дополнительной информации, на которую пользователь перенаправляется сразу после регистрации.
  • profiles.html — вывод профилей всех зарегистрированных пользователей с возможностью поиска по именам, интересам и ключевым словам в тексте «Обо мне».
  • user-profile.html — просмотр профиля любого пользователя.

Вся логика для создания, редактирования и удаления профилей находится в signals.py. В файле utils.py расположены функции для пагинации и поиска по профилям. Обратите внимание, что система поиска игнорирует профиль авторизованного пользователя, а функция пагинации является универсальной: она используется в других приложения блога для постраничного вывода записей, тестов и опросов. В файле users/forms.py расположены формы для регистрации и редактирования профиля, создания интересов и сообщений.

Модели в файле users/models.py описывают таблицы базы данных, которые связаны с хранением пользовательских профилей, интересов и сообщений. Слаги для интересов создаются автоматически: для транслитерации кириллицы используется функция slugify из модуля pytils.translit.

Функции представления users описаны в users/views.py — они обеспечивают:

  • регистрацию, аутентификацию и авторизацию пользователей,
  • добавление пользователей в друзья (и удаление из друзей),
  • создание и отправку сообщений,
  • редактирование профиля и интересов,
  • сортировку профилей по определенному интересу,
  • отправку сообщения из контактной формы с помощью SMTP.

Приложение блога

После добавления пользовательского функционала можно перейти к основному приложению — blog. Аналогичным образом создаем его, регистрируем в settings.py и инициализируем в urls.py корневой директории. Маршруты самого блога находятся в blog/urls.py, а шаблоны — в blog/templates/blog

  • my-blog.html — шаблон для отображения собственного блога авторизованного пользователя.
  • post_footer.html — футер поста для вывода количества лайков, закладок и комментариев.
  • post_form.html — шаблон с формой добавления новой записи.
  • post_list.html — «френдлента» и вывод записей по категориям и тегам.
  • single-post.html — вывод отдельного поста с комментариями.
  • user-blog.html — вывод блога любого пользователя.

Во время создания и редактирования записи пользователи могут выбирать существующие теги или добавлять новые: слаги для тегов создаются автоматически с помощью ранее упомянутого модуля pytils.translit. Метод генерации слагов get_unique_slug() для записей класса Post обеспечивает уникальность ссылок: если подобный слаг уже существует, к новому будет добавлен соответствующий порядковый номер:

    def get_unique_slug(self):
        slug = slugify(self.title)
        unique_slug = slug
        num = 1
        while Post.objects.filter(slug=unique_slug).exists():
            unique_slug = f"{slug}{num}"
            num += 1
        return unique_slug

Функция генерации уникального слага.

У класса Post есть и другие полезные методы:

  • number_of_likes() — возвращает число лайков.
  • number_of_bookmarks() — подсчитывает, сколько раз пользователи добавили запись в закладки.
  • number_of_comments() — определяет число одобренных и опубликованных комментариев. За одобрение комментариев отвечает метод approve() класса Comment.

Вся логика блога описана в blog/views.py. Функции представления отвечают за: 

  • добавление и удаление лайков и закладок,
  • сортировку записей по тегам и категориям,
  • вывод записей, добавленных в избранное, или отмеченных лайком,
  • постраничный вывод записей и поиск по ключевым словам. Сам поиск записей реализован с помощью модуля Django Q — соответствующая функция описана в blog/utils.py.

Тестовый запуск блога на сервере

Супер — большая часть функциональности уже готова. Можно загрузить код на сервер и протестировать работу приложения в продакшн-среде. Так оно будет доступно 24/7 вне зависимости от того, включена локальная машина или нет. 

На первых порах, когда пользователей у проекта еще мало, будет достаточно виртуального сервера с гибкой производительностью ядра. Для этого регистрируемся и входим в панель управления my.selectel.ru. Переходим в раздел Облачная платформа и выбираем Серверы

Создаем сервер и настраиваем конфигурацию. Минимальный вариант — 20% vCPU, 1 ГБ ОЗУ, базовый SSD-диск на 5 ГБ и Ubuntu в качестве операционной системы. С учетом публичного IP-адреса такая конфигурация выйдет примерно 25 рублей в день. 

Нажмите на бургер-меню в левом верхнем углу и перейдите в раздел Облачная платформа. Затем создайте новый проект.

Подготовка операционной системы и окружения

Для начала обновим Ubuntu, установим Git, Python, Nginx, файервол и вспомогательный пакет python3-dev. А также создадим виртуальное окружение и активируем его.

sudo apt upgrade
sudo apt install git ufw python3-pip python3-dev nginx
sudo apt install python3-venv
python3 -m venv blogitenv
source blogitenv/bin/activate

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

git clone https://github.com/natkaida/blogit.git
cd blogit
pip install -r requirements.txt

Далее нужно перейти в settings.py и установить значение False для параметра DEBUG. А в ALLOWED_HOSTS — добавить локальный и публичный адреса сервера, по которым будет доступен блог. Также не забудьте изменить значение SECRET_KEY и проверить конфигурации, которые используют приложения.

DEBUG = False
ALLOWED_HOSTS = ['94.26.224.162', 'localhost']

/root/blogit/config/settings.py

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

Теперь можно создать базу данных, аккаунт суперпользователя/администратора и собрать статические файлы в папку static, откуда их позже будет раздавать Nginx.

python3 manage.py migrate
python3 manage.py createsuperuser
python3 manage.py collectstatic

Пора проверить, как прошла установка приложения. Для этого запустим проект на нативном веб-сервере Django со специальным параметром --insecure, который позволяет фреймворку раздавать статические файлы в режиме DEBUG = False.

python3 manage.py runserver 0.0.0.0:8000 --insecure

Готово — сайт доступен из интернета по адресу http://94.26.224.162:8000.

Однако стандартный веб-сервер Django предназначен только для тестирования и запуска веб-приложений во время разработки. Для обработки запросов в продакшене нужен Nginx и WSGI Gunicorn.

Заключение

В этой части мы разобрали шаблон, в котором реализована основная функциональность платформы, и коснулись вопроса выбора хостинга. В следующей — расскажем, как настроить Nginx и Gunicorn для веб-приложения и развернуть почтовый сервер.