Введение
В предыдущем руководстве “Как создать приложение Django и подключить его к базе данных” мы рассмотрели, как создать базу данных MySQL, как создать и запустить приложение Django и как подключить его к базе данных MySQL.
В этом руководстве мы создадим модели Django, которые определяют поля и поведение данных приложения Blog, которые мы будем хранить. Эти модели отображают данные из вашего приложения Django в базу данных. Это то, что Django использует для генерации таблиц базы данных через свой API отображения объектов в отношения, называемый “моделями”.
Необходимые условия
Это руководство является частью серии “Разработка Django” и является продолжением этой серии.
Если вы не следовали за этой серией, мы делаем следующие предположения:
- У вас установлена Django версии 4 или выше.
- Вы подключили свое приложение Django к базе данных. Мы используем MySQL, и вы можете осуществить это подключение, следуя второй части серии Django, “Как создать приложение Django и подключить его к базе данных“.
- Вы работаете с операционной системой на основе Unix, предпочтительно с облачным сервером Ubuntu 22.04, так как это система, на которой мы проводили тестирование. Если вы хотите настроить Django в подобной среде, обратитесь к нашему руководству, “Как установить Django и создать среду разработки на Ubuntu 22.04“.
Поскольку это руководство в значительной степени занимается моделями Django, вы, возможно, сможете следовать ему, даже если у вас несколько другая настройка.
Шаг 1 — Создание приложения Django
Следуя философии Django о модульности, мы создадим приложение Django внутри нашего проекта, которое содержит все необходимые файлы для создания веб-сайта блога.
Всякий раз, когда мы начинаем работу с Python и Django, мы должны активировать наше виртуальное окружение Python и перейти в корневой каталог нашего приложения. Если вы следовали этой серии, вы можете сделать это, набрав следующее.
- cd ~/my_blog_app
- . env/bin/activate
- cd blog
Затем давайте выполним эту команду:
- python manage.py startapp blogsite
Это создаст наше приложение вместе с каталогом blogsite
.
На этом этапе учебного курса у вас будет следующая структура каталогов для вашего проекта:
my_blog_app/
└── blog
├── blog
│ ├── __init__.py
│ ├── __pycache__
│ │ ├── __init__.cpython-38.pyc
│ │ ├── settings.cpython-38.pyc
│ │ ├── urls.cpython-38.pyc
│ │ └── wsgi.cpython-38.pyc
│ ├── asgi.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── blogsite
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── migrations
│ │ └── __init__.py
│ ├── models.py
│ ├── tests.py
│ └── views.py
└── manage.py
Файл, на который мы сосредоточимся в этом учебнике, будет файл models.py
, который находится в каталоге blogsite
.
Шаг 2 — Добавление модели постов
Сначала нам нужно открыть и отредактировать файл models.py
, чтобы он содержал код для создания модели Post
. Модель Post
содержит следующие поля базы данных:
title
— Заголовок блога.slug
— Где хранятся и генерируются допустимые URL-адреса для веб-страниц.content
— Текстовое содержимое блога.created_on
— Дата создания записи.author
— Человек, написавший запись.
Теперь перейдите в каталог, где находится файл models.py
.
- cd ~/my_blog_app/blog/blogsite
Используйте команду cat
, чтобы показать содержимое файла в вашем терминале.
- cat models.py
Файл должен содержать следующий код, который импортирует модели, а также комментарий, описывающий, что нужно разместить в этом файле models.py
.
from django.db import models
# Создайте свои модели здесь.
Используя ваш любимый текстовый редактор, добавьте следующий код в файл models.py
. Мы будем использовать nano
в качестве нашего текстового редактора, но вы можете использовать то, что предпочтительнее.
- nano models.py
Внутри этого файла код для импорта API моделей уже добавлен, мы можем удалить комментарий, который следует за ним. Затем мы импортируем slugify
для создания слагов из строк, User
из Django для аутентификации и reverse
из django.urls
для большей гибкости в создании URL.
from django.db import models
from django.template.defaultfilters import slugify
from django.contrib.auth.models import User
from django.urls import reverse
Затем добавьте метод класса в класс модели, который мы будем называть Post
, с следующими полями базы данных: title
, slug
, content
, created_on
и author
. Добавьте их ниже ваших инструкций по импорту.
...
class Post(models.Model):
title = models.CharField(max_length=255)
slug = models.SlugField(unique=True, max_length=255)
content = models.TextField()
created_on = models.DateTimeField(auto_now_add=True)
author = models.TextField()
Далее добавим функционал для создания URL и функцию для сохранения поста. Это крайне важно, потому что это создает уникальную ссылку для соответствия нашему уникальному посту.
...
def get_absolute_url(self):
return reverse('blog_post_detail', args=[self.slug])
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.title)
super(Post, self).save(*args, **kwargs)
Теперь нам нужно сказать модели, каким образом посты должны быть упорядочены и отображены на веб-странице. Логика для этого будет добавлена во вложенный внутренний класс Meta
. Класс Meta
обычно содержит другую важную логику модели, не связанную с определением полей базы данных.
...
class Meta:
ordering = ['created_on']
def __unicode__(self):
return self.title
Наконец, добавим модель Comment
в этот файл. Это включает добавление еще одного класса с именем Comment
с models.Models
в его сигнатуре и определением следующих полей базы данных:
name
— Имя человека, размещающего комментарий.email
— Адрес электронной почты человека, оставившего комментарий.text
— Текст самого комментария.post
— Пост, к которому был оставлен комментарий.created_on
— Время создания комментария.
...
class Comment(models.Model):
name = models.CharField(max_length=42)
email = models.EmailField(max_length=75)
website = models.URLField(max_length=200, null=True, blank=True)
content = models.TextField()
post = models.ForeignKey(Post, on_delete=models.CASCADE)
created_on = models.DateTimeField(auto_now_add=True)
На этом этапе файл models.py
будет завершен. Убедитесь, что ваш файл models.py
соответствует следующему:
from django.db import models
from django.template.defaultfilters import slugify
from django.contrib.auth.models import User
from django.urls import reverse
class Post(models.Model):
title = models.CharField(max_length=255)
slug = models.SlugField(unique=True, max_length=255)
content = models.TextField()
created_on = models.DateTimeField(auto_now_add=True)
author = models.TextField()
def get_absolute_url(self):
return reverse('blog_post_detail', args=[self.slug])
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.title)
super(Post, self).save(*args, **kwargs)
class Meta:
ordering = ['created_on']
def __unicode__(self):
return self.title
class Comment(models.Model):
name = models.CharField(max_length=42)
email = models.EmailField(max_length=75)
website = models.URLField(max_length=200, null=True, blank=True)
content = models.TextField()
post = models.ForeignKey(Post, on_delete=models.CASCADE)
created_on = models.DateTimeField(auto_now_add=True)
Не забудьте сохранить и закрыть файл. Если вы используете nano, вы можете сделать это, набрав CTRL
и X
, затем Y
, затем ENTER
.
После настройки файла models.py
мы можем приступить к обновлению файла settings.py
.
Шаг 3 — Обновление настроек
Теперь, когда мы добавили модели в наше приложение, мы должны уведомить наш проект о существовании только что добавленного приложения blogsite
. Для этого добавим его в раздел INSTALLED_APPS
в файле settings.py
.
Перейдите в каталог, где находится ваш файл settings.py
.
- cd ~/my_blog_app/blog/blog
Откройте ваш файл settings.py
, например, с помощью nano.
- nano settings.py
Открыв файл, добавьте ваше приложение blogsite
в раздел INSTALLED_APPS
файла, как показано ниже.
# Определение приложений
INSTALLED_APPS = [
'blogsite',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
С добавлением приложения blogsite
вы можете сохранить и закрыть файл.
На данном этапе мы готовы перейти к применению этих изменений.
Шаг 4 — Создание миграций
После добавления наших моделей Post
и Comment
следующим шагом будет применение этих изменений, чтобы схема базы данных MySQL
распознала их и создала необходимые таблицы.
Сначала мы должны упаковать наши изменения модели в отдельные файлы миграций с помощью команды makemigrations
. Эти файлы подобны commits
в системе контроля версий, такой как Git.
Теперь, если вы перейдете в каталог ~/my_blog_app/blog/blogsite/migrations
и выполните команду ls
, вы заметите, что там есть только файл __init__.py
. Это изменится, как только мы добавим миграции.
Перейдите в каталог блога, используя команду cd
, например:
- cd ~/my_blog_app/blog
Затем выполните команду makemigrations
для manage.py
.
- python manage.py makemigrations
Затем вы должны получить следующий вывод в вашем терминальном окне:
OutputMigrations for 'blogsite':
blogsite/migrations/0001_initial.py
- Create model Post
- Create model Comment
Помните, когда мы перешли в /~/my_blog_app/blog/blogsite/migrations
и там был только файл __init__.py
? Если теперь вернуться в этот каталог при помощи команды cd
, мы заметим, что добавлены два элемента: __pycache__
и 0001_initial.py
. Файл 0001_initial.py
был автоматически создан, когда вы выполнили команду makemigrations
. Подобный файл будет создаваться каждый раз при выполнении команды makemigrations
.
Выполните команду less 0001_initial.py
из каталога, в котором он находится, если хотите ознакомиться с содержимым файла.
Теперь перейдите в ~/my_blog_app/blog
:
- cd ~/my_blog_app/blog
Поскольку мы создали файл миграции, мы должны применить изменения, описанные в этих файлах, к базе данных, используя команду migrate
. Но сначала давайте проверим, какие миграции уже существуют, используя команду showmigrations
.
- python manage.py showmigrations
Outputadmin
[X] 0001_initial
[X] 0002_logentry_remove_auto_add
[X] 0003_logentry_add_action_flag_choices
auth
[X] 0001_initial
[X] 0002_alter_permission_name_max_length
[X] 0003_alter_user_email_max_length
[X] 0004_alter_user_username_opts
[X] 0005_alter_user_last_login_null
[X] 0006_require_contenttypes_0002
[X] 0007_alter_validators_add_error_messages
[X] 0008_alter_user_username_max_length
[X] 0009_alter_user_last_name_max_length
[X] 0010_alter_group_name_max_length
[X] 0011_update_proxy_permissions
blogsite
[ ] 0001_initial
contenttypes
[X] 0001_initial
[X] 0002_remove_content_type_name
sessions
[X] 0001_initial
Вы заметите, что все миграции отмечены, за исключением той, которую мы только что создали с моделями Post
и Comment
.
Теперь давайте проверим, какие SQL
-запросы будут выполнены после применения миграций, используя следующую команду. Она принимает в качестве аргументов миграцию и заголовок миграции:
- python manage.py sqlmigrate blogsite 0001_initial
Ниже показан фактический SQL-запрос, который выполняется за кулисами.
Output--
-- Создать модель Post
--
CREATE TABLE `blogsite_post` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `title` varchar(255) NOT NULL, `slug` varchar(255) NOT NULL UNIQUE, `content` longtext NOT NULL, `created_on` datetime(6) NOT NULL, `author` longtext NOT NULL);
--
-- Создать модель Comment
--
CREATE TABLE `blogsite_comment` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `name` varchar(42) NOT NULL, `email` varchar(75) NOT NULL, `website` varchar(200) NULL, `content` longtext NOT NULL, `created_on` datetime(6) NOT NULL, `post_id` integer NOT NULL);
ALTER TABLE `blogsite_comment` ADD CONSTRAINT `blogsite_comment_post_id_de248bfe_fk_blogsite_post_id` FOREIGN KEY (`post_id`) REFERENCES `blogsite_post` (`id`);
Теперь давайте выполним миграции, чтобы они были применены к нашей базе данных MySQL.
- python manage.py migrate
Мы получим следующий вывод:
OutputOperations to perform:
Apply all migrations: admin, auth, blogsite, contenttypes, sessions
Running migrations:
Applying blogsite.0001_initial... OK
Вы успешно применили миграции.
Важно помнить, что существует три ограничения при использовании миграций Django с MySQL в качестве вашей базы данных, как указано в документации Django.
- Отсутствие поддержки транзакций вокруг операций изменения схемы. Другими словами, если миграция не удается успешно применить, вам придется вручную отменить изменения, которые вы внесли, чтобы попытаться другую миграцию. Невозможно откатиться к более ранней точке до того, как были внесены изменения в неудавшейся миграции.
- Для большинства операций изменения схемы MySQL полностью переписывает таблицы. В худшем случае сложность по времени будет пропорциональна количеству строк в таблице для добавления или удаления столбцов. Согласно документации Django, это может занять так много времени, как одна минута на каждый миллион строк.
- В MySQL существуют ограничения на длину имен столбцов, таблиц и индексов. Существует также ограничение на совокупный размер всех столбцов и индексов. В то время как некоторые другие системы могут поддерживать более высокие лимиты, созданные в Django, те же самые индексы не будут созданы с использованием базы данных MySQL.
При рассмотрении каждой базы данных для использования с Django обязательно взвешивайте плюсы и минусы каждой из них.
Шаг 5 — Проверка схемы базы данных
После завершения миграций мы должны проверить успешное создание таблиц MySQL, которые мы создали с использованием наших моделей Django.
Чтобы выполнить это, выполните следующую команду в терминале для входа в MySQL. Мы будем использовать djangouser
, который мы создали в предыдущем уроке.
- mysql blog_data -u djangouser
Теперь выберите нашу базу данных blog_data
. Если вы не знаете, какую базу данных вы используете, вы можете показать все базы данных с помощью SHOW DATABASES;
в SQL.
- USE blog_data;
Затем введите следующую команду для просмотра таблиц.
- SHOW TABLES;
Этот SQL-запрос должен показать следующее:
Output+----------------------------+
| Tables_in_blog_data |
+----------------------------+
| auth_group |
| auth_group_permissions |
| auth_permission |
| auth_user |
| auth_user_groups |
| auth_user_user_permissions |
| blogsite_comment |
| blogsite_post |
| django_admin_log |
| django_content_type |
| django_migrations |
| django_session |
+----------------------------+
12 rows in set (0.01 sec)
Среди таблиц есть blogsite_comment
и blogsite_post
. Это модели, которые мы только что создали. Давайте проверим, содержат ли они поля, которые мы определили.
- DESCRIBE blogsite_comment;
Output+------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+----------------+
| id | int | NO | PRI | NULL | auto_increment |
| name | varchar(42) | NO | | NULL | |
| email | varchar(75) | NO | | NULL | |
| website | varchar(200) | YES | | NULL | |
| content | longtext | NO | | NULL | |
| created_on | datetime(6) | NO | | NULL | |
| post_id | int | NO | MUL | NULL | |
+------------+--------------+------+-----+---------+----------------+
7 rows in set (0.00 sec)
- DESCRIBE blogsite_post;
Output+------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+----------------+
| id | int | NO | PRI | NULL | auto_increment |
| title | varchar(255) | NO | | NULL | |
| slug | varchar(255) | NO | UNI | NULL | |
| content | longtext | NO | | NULL | |
| created_on | datetime(6) | NO | | NULL | |
| author | longtext | NO | | NULL | |
+------------+--------------+------+-----+---------+----------------+
6 rows in set (0.00 sec)
Мы проверили, что таблицы базы данных успешно созданы из миграций модели Django.
Вы можете выйти из MySQL с помощью CTRL
+ D
, и когда вы готовы покинуть среду Python, вы можете выполнить команду deactivate
:
- deactivate
Отключение вашей среды программирования вернет вас к приглашению командного терминала.
Заключение
{
“error”: “Upstream error…”
}
Source:
https://www.digitalocean.com/community/tutorials/how-to-create-django-models