Django 5: асинхронный бекенд и эффектный фронтенд с минимальными затратами времени

Приветствую, друзья!

Уже давно у меня возникала мысль подробно, как в случае с FastAPI и Aiogram 3, разобрать «суровый» Django 5. Однако, из-за большого дефицита свободного времени и масштабности Django, руки до этого не доходили. Сегодня, как вы уже поняли, момент настал.

В этой статье будет минимум теории, и она пройдет в формате: ставим задачу на полноценный проект и вместе её решаем. В конце статьи будет голосование за продолжение данной темы. Поэтому, если вы захотите, чтобы я основательно раскрыл для вас тему Django 5, дайте знать через голосование, комментарий или подписку.

Из-за слабого отклика на некоторые предыдущие темы, такие как SQLAlchemy 2, Playwright и Docker, я их забросил. Посмотрим, как пойдет дело с Django 5.

План на сегодня

Обозначим задачу. К концу этой статьи мы не просто напишем наш первый проект на Django 5, но и развернем его на реальном хостинге, тем самым преодолевая основной страх разработчиков Django.

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

Для деплоя я буду использовать сервис Amvera Cloud. Основная причина — простота деплоя. Нам достаточно будет:

  1. Зарегистрироваться в Amvera Cloud.

  2. Создать проект.

  3. Одним кликом активировать домен.

  4. Сгенерировать файл настроек прямо на их сайте.

  5. Через стандартные GIT-команды загрузить файлы Django-проекта на хостинг Amvera Cloud.

  6. Весь процесс деплоя займет не больше 5 минут, так что обязательно дочитайте статью до конца.

О самом проекте

Сегодня мы создадим простой сайт, который будет демонстрировать гороскоп на завтра для любого знака зодиака. Чтобы было интереснее, гороскоп будем асинхронно парсить в момент обращения к знаку зодиака (об этом подробнее далее).

Фронтенд, а именно два шаблона, мы попросим сгенерировать одну нейросеть, обзор которой я уже делал неоднократно в своем Хабре — websim.ai.

В процессе написания кода мы затронем следующие темы: маршрутизация, работа со статическими файлами, асинхронное использование Django 5, работа с базой данных SQLite через встроенное ORM и многое другое.

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

Дисклеймер

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

Пожалуйста, давайте без негатива. Если у вас есть предложения по более простым практикам, сообщайте об этом в комментариях.

Немного теории

Django — это высокоуровневый веб-фреймворк на Python, предназначенный для быстрого и удобного создания веб-приложений. Он следует принципу «Don’t Repeat Yourself» (DRY), что позволяет уменьшить количество повторяющегося кода.

Django предоставляет множество инструментов и библиотек «из коробки», таких как админ-панель, система маршрутизации, ORM для работы с базой данных, аутентификация и многое другое (большую часть этих инструментов мы рассмотрим сегодня).

Мы будем работать с 5-й версией Django. Как и в предыдущих версиях, основное внимание уделяется улучшению производительности и удобству разработки. То, что нас будет интересовать сегодня — это продвинутая асинхронность, которой мы и воспользуемся.

Больше теоретической информации вы найдете в интернете, а мы приступим к написанию кода.

Начинаем писать код

Для начала создадим новый проект под наше будущее приложение. Я, как обычно, буду работать в PyCharm.

В проекте будут использованы некоторые «нестандартные» для Django библиотеки. Для удобства установим их через файл requirements.txt. Вот его пример:

beautifulsoup4==4.12.3
bs4==0.0.2
django==5.1
fake-useragent==1.5.1
httpx==0.27.2
gunicorn==20.1.0
whitenoise==6.7.0

Библиотеки gunicorn и whitenoise нам понадобятся только на этапе деплоя. Поэтому их можно добавить в файл requirements.txt уже на стадии подготовки проекта к развертыванию.

Django — основной фреймворк, на котором мы будем писать код, а библиотеки bs4, fake-useragent и httpx понадобятся для парсинга гороскопа.

Установим библиотеки:

pip install -r requirements.txt

Теперь приступим к созданию проекта Django (не путать с приложением). Для этого воспользуемся командой:

django-admin startproject project_name

Я назову проект zodiac:

django-admin startproject zodiac

В результате у нас появится папка с именем zodiac и одноименный конфигурационный пакет zodiac. Давайте сразу переместим файл requirements.txt в корневую директорию проекта (папка zodiac). Это облегчит процесс деплоя в будущем, так как все нужные файлы будут находиться в одном месте.

d7dfdf9f61e9cc0a82da2228455e7b4f.png

Теперь создадим наше первое и единственное приложение.

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

Для создания приложения:

cd zodiac
python manage.py startapp zodiac_app

114573f3f5f026f5110ad60f05b25d8a.png

Теперь нам необходимо зарегистрировать созданное приложение. Для этого в конфигурационном пакете (zodiac в моем случае) необходимо найти файл settings.py.

Там находим список INSTALLED_APPS и добавляем в него имя приложения:

INSTALLED_APPS = [
    …,
    'zodiac_app',
]

Теперь нам необходимо подготовить маршруты для созданного приложения. Маршрутов у нас будет всего 2:

  1. Главная страница

  2. Страница с гороскопом (будет динамически подставляться путь)

Для этого в пакете созданного приложения (zodiac_app) создадим файл urls.py и заполним его следующим образом:

from django.urls import path
from . import views


urlpatterns = [
    path('', views.index, name='home'),
]

Тут нужно немного разобраться.

В данном файле я определил маршрут для главной страницы нашего сайта. Данная запись указывает, что есть некоторое представление (функция) в файле views, которое будет отвечать за обработку главной страницы.

Опишем это представление в файле views.py:

from django.shortcuts import render


def index(request):
    return render(request, 
                  template_name='index.html', 
                  context={'title': 'Космический гороскоп - все знаки зодиака'})

Данный код подразумевает, что у нас есть файл index.html, который необходимо будет загрузить при вызове главной страницы сайта (это мы описали на прошлом шаге, когда привязали данное представление к корню сайта).

Параметр context может принимать словарь с данными. В него мы пока просто передадим название страницы (это нужно будет для тестов).

Создадим максимально простой HTML.

Для хранения html шаблонов (напомню, у нас их всего 2 будет) необходимо создать папку templates в корне приложения (у меня это zodiac_app) и во внутрь положим файл index.html.




    
    
    
    {{ title }}


{{ title }}

Стандартный HTML. В него, чтоб проверить что переменные контекста корректно передаются я передал переменную title (для этого используются двойные фигурные скобки).

Теперь, перед первым запуском нашего приложения, нам необходимо будет включить страницы приложения. Для этого в конфиг-пакете (у меня это zodiac) находим файл urls.py и добавляем там следующее.

from django.urls import path, include


urlpatterns = [
    path('', include('zodiac_app.urls'))
]

Админку можно убрать, так как ее мы не будем использовать в данном проекте.

Благодаря такой записи мы включили маршруты из нашего приложения zodiac_app.

Теперь мы можем запустить сервер Django. Для этого нужно воспользоваться командой:

python manage.py runserver PORT

У меня свободен порт 5000, а значит команда запуска будет выглядеть так:

python manage.py runserver 5000

35ec460c32dea384e1f1d37a2b686db5.png

Перейдем на сервер

e410d488cfdd3e2ce312b2b2718e424e.png

Посмотрим на исходный код страницы (CTRL + U)

27f21ee84165aaaa541eb90e9aa50b53.png

Видим, что наш шаблон отработал корректно. Продолжим.

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

Для написания создадим файл utils.py в пакете приложения (zodiac_app).

897f2dce86c89f443e5d97e238d8b4a0.png

Логика парсера

Данные мы будем брать с сайта https://horo.mail.ru/prediction. Там, если переходить на страницу с гороскопом, то, по умолчанию, открывается страница следующей конструкции: https://horo.mail.ru/prediction/HOROSCOP_NAME_EN/today/. К этому мы и подстроим свой парсер.

То есть, мы будем передавать название знака зодиака на английском и будем вытягивать с этого сайта гороскоп на завтра. Для этого мы будем использовать httpx для асинхронной отправки запроса к сайту с гороскопом и bs4 для извлечения текста с гороскопом.

Полный код парсера

import httpx
from bs4 import BeautifulSoup
from fake_useragent import UserAgent


async def fetch_horoscope(zodiac_en="cancer"):
    # Создаем фейковый User-Agent
    ua = UserAgent()
    headers = {
        'accept': '*/*',
        'accept-language': 'ru,en;q=0.9',
        'cache-control': 'no-cache',
        'pragma': 'no-cache',
        'priority': 'u=0, i',
        'referer': 'https://horo.mail.ru/prediction/',
        'sec-ch-ua': '"Not/A)Brand";v="8", "Chromium";v="126", "YaBrowser";v="24.7", "Yowser";v="2.5"',
        'sec-ch-ua-mobile': '?0',
        'sec-ch-ua-platform': '"Windows"',
        'sec-fetch-dest': 'document',
        'sec-fetch-mode': 'navigate',
        'sec-fetch-site': 'same-origin',
        'sec-fetch-user': '?1',
        'upgrade-insecure-requests': '1',
        'user-agent': ua.random,  # Используем фейковый User-Agent
    }

    # Асинхронный HTTP-запрос
    async with httpx.AsyncClient() as client:
        response = await client.get(f'https://horo.mail.ru/prediction/{zodiac_en}/today/', headers=headers)

    # Парсинг ответа с помощью BeautifulSoup
    soup = BeautifulSoup(response.text, 'html.parser')
    main_content = soup.find('main', itemprop='articleBody')

    # Извлечение текста из найденного элемента, с разделением на строки
    text_lines = main_content.get_text(separator="\n", strip=True).splitlines()

    # Формирование новых 

для каждой строки текста paragraphs = ''.join([f'

{line}

' for line in text_lines]) return paragraphs

Для того чтоб сильно на этом не заострять внимание оставил комментарии в коде.

На что стоит обратить внимание — это подставка фейкового User Agent в заголовки. Далее все просто:

  • подставили название на английском гороскопа

  • отправили запрос на получение данных

  • через bs4 вытянули из полученных данных описание гороскопа

  • очистили от лишних классов и вернули html

Проверим код на знаке «Весы»

print(asyncio.run(fetch_horoscope(zodiac_en="aries")))

Получаем нужный результат. Отлично!

Получаем нужный результат. Отлично!

Теперь нам нужно подготовить красивые HTML шаблоны для нашего сайта. Воспользуемся нейросетью websim.ai

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

Страница гороскопа на русском языке. На ней размещена иконка гороскопа (фото), под ней — название на русском и дата рождения, соответствующая этому знаку. Также есть кнопка «Смотреть гороскоп». Сделай стильно и красиво, но без излишних усложнений.

Страница гороскопа на русском языке. На ней размещена иконка гороскопа (фото), под ней — название на русском и дата рождения, соответствующая этому знаку. Также есть кнопка «Смотреть гороскоп». Сделай стильно и красиво, но без излишних усложнений.

теперь оформи все 12 знаков на одной странице

теперь оформи все 12 знаков на одной странице

теперь добавь более красивые иконки под каждый гороскоп и выполни все в космическом стиле

теперь добавь более красивые иконки под каждый гороскоп и выполни все в космическом стиле

Фон получился динамическим, при наведении увеличивается кнопка. Лично я остался полностью доволен главной страницей. Теперь сохраним получившийся HTML.

1ae963da9274e80975dd756e28bd24ff.png

Теперь, в один промт, попросим подготовить для нас страничку с гороскопом.

оформи в этом же стиле страницу внутри гороскопа. иконка, описание и кнопка

оформи в этом же стиле страницу внутри гороскопа. иконка, описание и кнопка «На главную». Обязательно сохрани общий стиль

И этой страницей я полностью доволен и теперь остается только ее сохранить.

3130635692cee8d790b76bb9e8f2960f.png

Работа с базой данных

К шаблонам мы вернемся чуть позже, а сейчас подготовим простую базу данных под наш проект. В этой базе данных мы создадим одну таблицу и будем хранить в ней следующие поля: русское название зодиака, английское название зодиака, день когда начинается знак, день когда заканчивается знак и svg (нейронка сгенерировала все иконки чистым svg, так что в этом поле будем хранить HTML).

Для работы с базой данных в Django используется объектно-ориентированный подход. Если простыми словами, то создается класс таблицы и далее работа идет с каждым полем как с отдельным объектом класса.

Для работы нам необходимо создать модель таблицы. Файл для моделей уже создан в нашем приложении (zodiac_app) — models.py. Опишем модель.

from django.db import models


class ZodiacSign(models.Model):
    zodiac_ru = models.CharField(max_length=50, unique=True)  # Название знака зодиака на русском
    zodiac_en = models.CharField(max_length=50, unique=True)  # Название знака зодиака на английском
    start_day = models.CharField(max_length=20, unique=True)  # Дата начала периода
    end_day = models.CharField(max_length=20, unique=True)  # Дата окончания периода
    svg = models.TextField()  # SVG-код

    def __str__(self):
        return self.zodiac_en

Описание очень похоже на работу с SQLAchemy. В комментариях дал описание на русском каждого поля.

Теперь нам необходимо создать миграцию на основе нашей модели.

Миграции — это способ управления изменениями в структуре базы данных. После того как вы описали модель, Django должен создать миграции, чтобы применить эти изменения в базе данных.

Выполним команду:

python manage.py makemigrations

Эта команда создаст файлы миграций в директории migrations вашего приложения.

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

Выполните команду:

python manage.py migrate

Эта команда применит все созданные миграции и обновит структуру базы данных.

9725add4db0cfe42a1fa5e5f28c59d01.png

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

bc9a948f0220bffe19bd75cbca9af116.png

Если у вас была описана всего одна модель, то будет создана одна таблица. Напоминаю, что по умолчанию Django ориентирован на SQLite.

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

Название на русском, день начала, день завершения и название на английском (со ссылки)

Название на русском, день начала, день завершения и название на английском (со ссылки)

На выходе у меня получился такой массив данных:

zodiac_data = [
    {
        'zodiac_ru': 'овен',
        'zodiac_en': 'aries',
        'start_day': '20 марта',
        'end_day': '19 апреля',
        'svg': '''
            
            
            
                
                    
                    
                
            
        '''
    }, …]

Кому будет нужно — с полным кодом всего проекта можно ознакомиться в моем телеграмм-канале «Легкий путь в Python».

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

from django.db import models


zodiac_data = [...]


class ZodiacSign(models.Model):
    zodiac_ru = models.CharField(max_length=50, unique=True)  # Название знака зодиака на русском
    zodiac_en = models.CharField(max_length=50, unique=True)  # Название знака зодиака на английском
    start_day = models.CharField(max_length=20, unique=True)  # Дата начала периода
    end_day = models.CharField(max_length=20, unique=True)  # Дата окончания периода
    svg = models.TextField()  # SVG-код

    def __str__(self):
        return self.zodiac_en


def bulk_create_zodiac_signs():
    # Создаем список объектов модели
    zodiac_signs = [
        ZodiacSign(
            zodiac_ru=data['zodiac_ru'],
            zodiac_en=data['zodiac_en'],
            start_day=data['start_day'],
            end_day=data['end_day'],
            svg=data['svg']
        )
        for data in zodiac_data
    ]

    # Используйте bulk_create для добавления всех записей
    ZodiacSign.objects.bulk_create(zodiac_signs)

Данные для добавления в таблицу я подготовил там-же.

Теперь войдем в оболочку Django и с нее выполним функцию bulk_create_zodiac_signs. Для этого:

  • Вводим команду:

    python manage.py shell

  • Импортируем функцию bulk_create_zodiac_signs

    from zodiac_app.models import bulk_create_zodiac_signs

  • Выполняем функцию

    bulk_create_zodiac_signs()

  • Выходим с оболочки:

    exit()

e90849850d753f7763fad69d82c72914.png

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

Все данные на месте

Все данные на месте

Все данные на месте, парсер написан и это значит что мы можем приступать к оформлению HTML-шаблонов.

Оформление HTML-шаблонов

Конечно, мы все сделаем по-красоте. Для этого, для начала, в папке приложения (zodiac_app) подготовим папку templates и внутри нее следующие папки: img (для фото), js (для JavaScript скриптов) и style (для CSS-стилей).

fb951373a42b51ab3a34bd8d38399b01.png

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

Для начала, я создал файл стилей main.css и в него перенес все стили с блока стилей, который подготовила нейросеть. Так как стилей много — просто приведу в пример скриншот (где искать исходники проекта вы знаете).

ac8dd19bb5337243cefbbf433c867942.png

Далее, на главной странице, как вы могли заметить, представлены знаки зодиака плиткой, а это хорошая предпосылка для нас, так как мы сможем на основании каждой такой карточки оформить внутренний цикл FOR и просто переберем все значения с базы данных в HTML-шаблоне.

Сама карточка от нейронки имеет такой вид:

Близнецы

21 мая - 20 июня

Смотреть гороскоп

И в таком формате 12 раз. Адаптируем код под наш проект:

{% load static %}


    
    
    {{ title }}
    
    
    
    


{% for info in main_data %}
{{ info.svg|safe }}

{{ info.zodiac_ru|title }}

{{ info.start_day }} - {{ info.end_day }}

Смотреть гороскоп
{% endfor %}

Это весь код главной страницы.

Тут стоит обратить внимание на начало файла. Я использовал {% load static %}. Благодаря этому мы указали Django что в этот файл необходимо подключить статические файлы (например, CSS, изображения).

Кроме того, я заранее подготовил иконку (фавикон) и закинул ее в папку img. Затем я импортировал файл стилей.

Далее, из интересного, это основной цикл. В данном случае я использовал внутренний цикл FOR из шаблонизатора Django. В качестве перебора я воспользовался списком main_data (этот список мы получим с базы данных совсем скоро и передадим его в шаблон).

Смотреть гороскоп

Благодаря этой строке, для страницы с гороскопом будет сформирована ссылка такого вида: http://127.0.0.1:5000/aries. Это мы используем в дальнейшем, когда опишем страницу каждого гороскопа.

Теперь изменим функцию-представления для главной страницы.

Для начала импортируем модель нашей таблицы в файл views.py

from .models import ZodiacSign

Теперь в представление index добавим обращение к базе данных с целью получения всех записей. С DjangoORM это делать очень просто.

def index(request):
    main_data = ZodiacSign.objects.all()
    return render(request,
                  template_name='index.html',
                  context={'title': 'Космический гороскоп - все знаки зодиака', 'main_data': main_data})

Всего одной строкой: main_data = ZodiacSign.objects.all () нам удалось извлечь все записи с нашей созданной таблицы. Каждая из этих записей теперь представлена списком питоновских словарей, что позволит нам обращаться к каждому значению через точку в шаблоне.

Перезапустим сервер и посмотрим что получилось с главной.

4d84916529f96f512fee214a66badc3d.png

Получилось то что я планировал. Все записи выстроились корректно, стили подгрузились.

Теперь остается настроить представление для страницы с гороскопом.

Для начала поработаем с маршрутом (файл zodiac_app/urls.py).

urlpatterns = [
    path('', views.index, name='home'),
    path('/', views.zodiac, name='zodiac'),
]

Тут мы добавили новый маршрут для представления zodiac.

  •  — это динамическая часть URL, которая может принимать различные значения. Django распознает этот параметр и передает его в соответствующее представление в качестве аргумента.

  • slug — это конвертер, который ограничивает формат значения переменной zodiac_name. Он ожидает строку, состоящую из букв, цифр, дефисов и подчеркиваний (например, aries, leo, virgo, scorpio-2023). Slug используется для создания «чистых» URL, удобных для чтения и SEO.

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

Для начала мы импортируем метод sync_to_async из asgiref.sync (ветка у вас уже установлена). Данный метод позволит превратить синхронный код в асинхронный, что уже следует из названия.

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

from asgiref.sync import sync_to_async


@sync_to_async
def get_zodiac_data(zodiac_name):
    return ZodiacSign.objects.get(zodiac_en=zodiac_name)

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

И опишем само представление.

async def zodiac(request, zodiac_name):
    zodiac_data = await get_zodiac_data(zodiac_name)
    html_description = await fetch_horoscope(zodiac_name)
    return render(request, 'zodiac_page.html',
                  {'title': zodiac_name, 'zodiac_data': zodiac_data, 'html_description': html_description})

Теперь у нас полностью асинхронное представление. Работает код по следующей логике:

  1. Получаем данные по знаку зодиака с базы данных

  2. Получаем описание гороскопа на завтра с сайта с гороскопом (не забудьте предварительно выполнить импорт парсера из утилит from .utils import fetch_horoscope

  3. Далее выполняем знакомый рендер (html шаблон у нас уже есть и его нужно только адаптировать).

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

{% load static %}


    
    
    Ваш космический гороскоп для {{ zodiac_data.zodiac_ru|title }}
    
    


{{ zodiac_data.svg|safe }}

{{ zodiac_data.zodiac_ru|title }}

{{ html_description|safe}} На главную

Из нового только импорт js-скрипта и использование safe для корректного отображения HTML.

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

@sync_to_async
def get_all_zodiac_signs():
    return list(ZodiacSign.objects.all())


async def index(request):
    main_data = await get_all_zodiac_signs()
    return render(request, 'index.html', {'main_data': main_data})

Теперь перезапустим сервер и посмотрим на результат.

506bebe7ed2d36b8d80346d1f1290d34.png

Сверим результат с тем что на сайте-доноре.

752998695ec8faa2d9a977706ada42bb.png

Видим что результат одинаков, а это значит что проект готов!

Подготовка к деплою

Сегодня я продемонстрирую один из самых простых способов деплоя Django приложения, используя отечественный аналог Heroku — Amvera Cloud. Перед этим подготовим наш проект.

Сначала настроим файл settings.py, где мы ранее регистрировали наше приложение.

Переведём проект из режима разработки:

DEBUG = False

Настроим разрешения доступа к сайту. Так как проект учебный, разрешим доступ со всех адресов:

ALLOWED_HOSTS = ['*']

Чтобы упростить работу со статическими файлами, добавим в список middleware следующую строку:

MIDDLEWARE = [
    …,
    'whitenoise.middleware.WhiteNoiseMiddleware',
]

WhiteNoise позволяет эффективно управлять статическими файлами, что особенно полезно, когда нет возможности использовать полноценный веб-сервер. Эта настройка избавляет от необходимости дополнительной конфигурации Nginx или Apache для обработки статики.

Затем укажем путь для хранения статических файлов в продакшене:

STATIC_URL = '/static/'
STATIC_ROOT = BASE_DIR / 'static'

STATIC_URL = '/static/' определяет базовый URL для доступа к статическим файлам, а STATIC_ROOT = BASE_DIR / 'static' — директорию на сервере, куда будут собираться все статические файлы при выполнении команды collectstatic.

Деплой приложения

Теперь мы полностью готовы к деплою.

  • Зарегистрируйтесь на сайте Amvera Cloud, если еще не зарегистрированы (за регистрацию предусмотрен бонус в размере 111 рублей на основной счет).

  • Перейдите в раздел проектов.

  • Нажмите на «Создать проект», задайте ему название и выберите тариф.

  • Следующий экран пропустите — к нему мы вернемся позже.

  • На открывшемся экране появится возможность сгенерировать файл настроек. Заполните данные, как указано на скриншоте ниже (при необходимости их можно будет изменить позже).

04aaac2c9019c7177865df7ef7ccdf2e.png

  • Нажмите на «Завершить».

  • Войдите в проект, откройте вкладку «Настройки» и активируйте бесплатный домен (если у вас есть свой домен, его можно привязать на этом же экране).

2064b515f6e71b35d1a5ed99f83eee74.png801a82c948db869fbdf06edbbb0ce133.png

На этом все настройки на стороне Amvera Cloud завершены. Теперь осталось с помощью GIT доставить файлы нашего Django проекта в проект на Amvera, после чего проект автоматически развернется и запустится (магия).

Перейдите в корень проекта (папка zodiac) и инициализируйте пустой Git-репозиторий:

git init

Привяжите проект к Amvera. В моем случае команда выглядит так:

git remote add amvera https://git.amvera.ru/yakvenalex/djangozodiac

Заберите файл настроек:

git pull amvera master

В моем случае файл имеет такой вид:

---
meta:
  environment: python
  toolchain:
    name: pip
    version: 3.12
build:
  requirementsPath: requirements.txt
run:
  persistenceMount: /data
  containerPort: 5000
  command: gunicorn zodiac.wsgi:application  --bind 0.0.0.0:5000

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

f5450bc0beba24843edb9c9755cccf02.png

Для запуска важно наличие всех этих файлов именно в такой иерархии. Иначе запуск не произойдет.

Теперь доставим файлы:

git add .
git commit -m "init commit"
git pull amvera master

Если все прошло корректно, то после обновления, на вкладке «Репозиторий» вы должны увидеть файлы своего проекта.

96052c4a000e8665b1321b3500ac2589.png

После автоматически начнется сборка проекта и, если все было сделано правильно, то минут через 5 вы увидите следующее.

e4b71da9de6967ae0279081812d4c065.png

Теперь остается только перейти по доменному имени проекта и проверить все ли работает. В моем случае это: https://djangozodiac-yakvenalex.amvera.io/

Главный экран

Главный экран

Страница с гороскопом

Страница с гороскопом

Заключение

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

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

Полный исходный код проекта, а также дополнительный эксклюзивный контент, который я не планирую публиковать на Хабре, вы сможете найти в моем телеграм-канале «Легкий путь в Python».

Напоминаю, что если вам интересно получить более подробное и глубокое погружение в фреймворк Django в моем авторстве, участвуйте в голосовании под этой статьей, ставьте лайки и оставляйте комментарии. Это займет у вас всего пару секунд, а мне будет очень приятно.

Спасибо за внимание и до скорого!

© Habrahabr.ru