В уроке 2 по созданию API на Django REST Framework, мы рассмотрим создание приложения Блога, а также создание модели Статьи и модели Категории.
Примечание: в проекте я буду использовать декомпозицию и разделение всех элементов, для удобности масштабирования.
Создание модуля «Блог»
В папке backend нашего проекта я создам каталог modules с пустым файлом __init__.py
Далее я введу команду с активированным виртуальным окружением в терминале: py manage.py startapp blog
Полученную папку с модулем blog я перемещаю в созданную вручную папку modules. Если вы используете PyCharm, у Вас некоторые пути в файлах модуля blog поменяются автоматически, если же вы работаете через VS CODE, то Вам необходимо изменить файл apps.py модуля blog:
modules/blog/apps.py
С этого:
from django.apps import AppConfig
class BlogConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'blog'
На это:
from django.apps import AppConfig
class BlogConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'modules.blog'
verbose_name = 'Модуль: Блог'
Пояснение:
- При подключении модуля blog в главный файл-конфиг settings.py нам не будет сыпаться ошибка, а все будет работать корректно.
- Также добавил сразу русифицированное название при использовании админки, а именно
verbose_name = 'Модуль: Блог'
Подключение модуля в settings.py в INSTALLED_APPS:
engine/settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
'modules.blog.apps.BlogConfig',
]
Создание модели «Статьи»
Внутри модуля blog я создам папку models с файлом __init__.py.
Далее, внутри папки models я добавлю файл articles.py со следующим содержимым:
modules/blog/models/articles.py
from django.db import models
from django.core.validators import FileExtensionValidator
class Article(models.Model):
title = models.CharField(verbose_name='Заголовок', max_length=255)
slug = models.SlugField(verbose_name='URL', max_length=255, blank=True)
short_description = models.TextField(max_length=300, verbose_name='Краткое описание')
full_description = models.TextField(verbose_name='Полное описание')
created_at = models.DateTimeField(verbose_name='Дата добавления', auto_now_add=True, db_index=True)
updated_at = models.DateTimeField(verbose_name='Дата обновления', auto_now=True, db_index=True)
thumbnail = models.ImageField(
verbose_name='Превью поста',
blank=True,
upload_to='images/thumbnails/',
validators=[FileExtensionValidator(
allowed_extensions=('png', 'jpg', 'webp', 'jpeg', 'gif'))
]
)
is_published = models.BooleanField(default=True, verbose_name='Опубликовано')
is_fixed = models.BooleanField(default=False, verbose_name='Зафиксировано')
# Связи по ключам
category = models.ForeignKey(to='Category', on_delete=models.PROTECT, null=True, verbose_name='Категория')
class Meta:
ordering = ('-is_fixed', '-created_at',)
verbose_name = 'Статья'
verbose_name_plural = 'Статьи'
db_table = 'app_articles'
def __str__(self):
return self.title
Пояснение:
- Создаем модель Статьи с полями: заголовка (title), слага (slug: чпу - человеко-понятный-урл), краткого описания (short_description), полного описания (full_description), времени добавления (created_at), времени изменения статьи (updated_at), превью статьи (thumbnail), опубликована ли статьи (is_published), зафиксирована ли статья на главной (is_fixed).
- Также я добавил поле с внешними связями, а именно связи с категориями (category), которые мы создадим ниже по руководству.
- Добавил мета информацию в виде сортировки (ordering), название в единственном числе (verbose_name) и во множественном (verbose_name_plural), и название таблицы в базе данных (db_table)
- Метод
__str__
будет возвращать нам заголовок статьи (title) в административной части, или при использовании ORM в режиме Shell.
Создание модели «Категория»
Внутри папки models я добавлю файл categories.py со следующим содержимым:
modules/blog/models/categories.py
from django.db import models
class Category(models.Model):
title = models.CharField(verbose_name='Заголовок', max_length=255)
slug = models.SlugField(verbose_name='URL', max_length=255, blank=True)
description = models.TextField(max_length=300, verbose_name='Описание')
class Meta:
ordering = ('title',)
verbose_name = 'Категория'
verbose_name_plural = 'Категории'
db_table = 'app_categories'
def __str__(self):
return self.title
Пояснение:
- Создаем модель Категории с полями: заголовка (title), слага (slug: чпу - человеко-понятный-урл), описания (description).
- Добавил мета информацию в виде сортировки (ordering), название в единственном числе (verbose_name) и во множественном (verbose_name_plural), и название таблицы в базе данных (db_table)
- Метод
__str__
будет возвращать нам заголовок категории (title) в административной части, или при использовании ORM в режиме Shell.
Если вы сделали папку models, и все модели размещаете отдельно по файлам как я, то Вам необходимо настроить файл __init__.py. Данная процедура облегчает импорты моделей в другие файлы, как бы это было если бы мы разместили все модели в одном файле models.py
Если же Вы так не делаете, то этим заниматься не нужно!
modules\blog\models\__init__.py
from modules.blog.models.articles import Article
from modules.blog.models.categories import Category
__all__ = '__all__'
Отлично. Осталось установить пакет Pillow для работы с изображениями и провести миграции:
Установка Pillow для работы с изображениями осуществляется с помощью следующей команды в терминале: pip install Pillow
Результат установки:
(venv) PS C:\Users\Razilator\Desktop\Projects\App\backend> pip install Pillow
Collecting Pillow
Downloading Pillow-9.3.0-cp310-cp310-win_amd64.whl (2.5 MB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 2.5/2.5 MB 2.7 MB/s eta 0:00:00
Installing collected packages: Pillow
Successfully installed Pillow-9.3.0
[notice] A new release of pip available: 22.2.2 -> 22.3.1
[notice] To update, run: python.exe -m pip install --upgrade pip
Теперь нам нужно создать миграции и провести их.
Для создания миграций вводим команду: py manage.py makemigrations
Результат:
(venv) PS C:\Users\Razilator\Desktop\Projects\App\backend> python manage.py makemigrations
Migrations for 'blog':
modules\blog\migrations\0001_initial.py
- Create model Category
- Create model Article
Теперь применяем миграции. За базу данных у нас будет выступать пока-что SQLITE.
Применение миграций с помощью команды: py manage.py migrate
Результат всех миграций:
(venv) PS C:\Users\Razilator\Desktop\Projects\App\backend> py manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, blog, 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 auth.0010_alter_group_name_max_length... OK
Applying auth.0011_update_proxy_permissions... OK
Applying auth.0012_alter_user_first_name_max_length... OK
Applying blog.0001_initial... OK
Applying sessions.0001_initial... OK
Отлично. Теперь давайте взглянем на скриншот, чтобы Вы убедились, что вы сделали все также:

Если у Вас получилось также, вы большой молодец, а если Вы сделали по-своему как-то, то вы ещё какой молодец 😊👍🏻
Давайте сразу создадим суперпользователя, делается это командой: py manage.py createsuperuser

Суперпользователь добавлен.
Давайте подключим наши модели к административной части Django, чтобы мы имели доступ добавлять сами статьи.
Находим файл admin.py в папке модуля blog, и добавляем следующее содержимое:
from django.contrib import admin
from modules.blog.models import Article, Category
admin.site.register(Article)
admin.site.register(Category)
Обратите внимание на импорты моделей Article, Category, это все мы сделали с помощью файла __init__.py, учитывая, что эти модели разделены по разным файлам.
Давайте авторизуемся в административной части и посмотрим на созданные модели, перейдем на страницу: http://127.0.0.1:8000/admin/, авторизуемся с помощью созданного логина и пароля.

Здесь мы можем добавить любые данные. Но об этом уже поговорим в следующем 3 уроке.