Как создавать модели Django

0 Акции
0
0
0
0

Введение

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

Предпосылки

Это руководство является частью серии «Разработка Django» и ее продолжением.

Если вы не следили за этой серией, мы делаем следующие предположения:

  • У вас установлен Django версии 4 или выше.
  • Вы подключили свое приложение Django к базе данных.
  • Вы работаете с операционной системой на базе Unix, предпочтительно с облачным сервером Ubuntu 22.04, поскольку именно на этой системе мы проводили тестирование.

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

Шаг 1 — Создание приложения Django

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

Каждый раз, когда мы начинаем работать с Python и Django, нам необходимо активировать виртуальную среду Python и переместить её в корневой каталог нашего приложения. Если вы следовали инструкциям, вы можете сделать это, выполнив следующую команду.

cd ~/my_blog_app
. env/bin/activate
cd blogr code... */

Теперь давайте выполним эту команду:

python manage.py startapp 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, который находится в каталоге блога сайта.

Шаг 2 — Добавьте шаблоны постов

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

  • TITLE – Название записи в блоге.
  • Slug – место, где хранятся и генерируются действительные URL-адреса веб-страниц.
  • СОДЕРЖАНИЕ – Текстовое содержание записи в блоге.
  • create_on – Дата создания поста.
  • АВТОР – Человек, написавший пост.

Теперь перейдите в каталог, где находится файл models.py.

cd ~/my_blog_app/blog/blogsite

Используйте команду cat для отображения содержимого файла в терминале.

cat models.py

Файл должен содержать следующий код, импортирующий модели, а также комментарий, поясняющий, что содержится в этом файле models.py.

from django.db import models
# Create your models here.

Используя ваш любимый текстовый редактор, добавьте следующий код в файл models.py. Мы будем использовать nano в качестве текстового редактора, но вы можете использовать любой другой.

nano models.py

В этом файле уже добавлен код для импорта моделей API, поэтому мы можем удалить комментарий ниже. Затем мы импортируем slugify для генерации слагов из строк, пользователя Django для аутентификации и обратный путь из 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

Затем добавьте метод класса со следующими полями базы данных: title, slug, content, created_on и author, в класс модели, который мы назовём Post. Добавьте их под операторами импорта.

...
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)

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

...
class Meta:
ordering = ['created_on']

def __unicode__(self):
return self.title

Наконец, мы добавляем в этот файл модель Comment. Это включает в себя добавление ещё одного класса Comment с сигнатурой models.Models и определение следующих полей базы данных:

  • ИМЯ – Имя человека, отправившего комментарий.
  • EMAIL – адрес электронной почты лица, отправившего комментарий.
  • ТЕКСТ – Текст самого комментария.
  • ПОСТ – пост, к которому был добавлен комментарий.
  • create_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

Открыв файл, добавьте приложение блога вашего сайта в раздел INSTALLED_APPS файла, как показано ниже.

# Application definition
INSTALLED_APPS = [
'blogsite',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]

После добавления блог-приложения сайта вы можете сохранить файл и выйти.

На этом этапе мы готовы приступить к внедрению этих изменений.

Шаг 4 — Выполнение миграции

После добавления моделей Post и Comment следующим шагом будет применение этих изменений, чтобы наша схема базы данных MySQL распознала их и создала необходимые таблицы.

Для начала нам нужно упаковать изменения нашей модели в отдельные файлы миграции с помощью команды makemigrations. Эти файлы аналогичны коммитам в системе контроля версий, например, Git.

Теперь, если вы перейдете в ~/my_blog_app/blog/blogsite/migrations и выполните команду ls, вы увидите, что там только один файл __init__.py. Это изменится, когда мы добавим миграции.

Перейдите в каталог блога с помощью cd, например так:

cd ~/my_blog_app/blog

Затем выполните команду makemigrations в manager.py.

python manage.py makemigrations

После этого в окне терминала должен появиться следующий вывод:

Output
Migrations for 'blogsite':
blogsite/migrations/0001_initial.py
- Create model Post
- Create model Comment

Помните, как мы перешли в /~/my_blog_app/blog/blogsite/migrations, а там был только файл __init__.py? Если мы сейчас вернёмся в этот каталог, то заметим, что добавлены ещё два элемента: __pycache__ и 0001_initial.py. Файл 0001_initial.py был автоматически создан при запуске makemigrations. Аналогичный файл будет создаваться каждый раз при запуске makemigrations.

Если вы хотите прочитать содержимое файла, просто запустите 0001_initial.py из каталога, в котором он находится.

Теперь перейдите в ~/my_blog_app/blog:

cd ~/my_blog_app/blog

Поскольку мы создали файл миграции, нам необходимо применить описанные в нём изменения к базе данных с помощью команды migrate. Но сначала давайте проверим, какие миграции существуют в данный момент, с помощью команды showmigrations.

python manage.py showmigrations
Output
admin
[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

Вы заметите, что все миграции проверены, за исключением одной для 0001_initial, которую мы создали с помощью моделей Post и Comment.

Теперь давайте проверим, какие SQL-операторы выполняются после завершения миграций, используя следующую команду. Она принимает миграцию и её заголовок в качестве аргумента:

python manage.py sqlmigrate blogsite 0001_initial

Ниже показан реальный SQL-запрос, выполняемый «за кулисами».

Output
--
-- Create model 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);
--
-- Create model 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

Мы получим следующий вывод:

Output
Operations to perform:
Apply all migrations: admin, auth, blogsite, contenttypes, sessions
Running migrations:
Applying blogsite.0001_initial... OK

Вы успешно применили свои миграции.

Важно помнить, что, как указано в документации Django, при миграции Django с MySQL в качестве бэкэнда есть три предостережения.

  • Отсутствует поддержка транзакций, связанных с операциями изменения схемы. Другими словами, в случае сбоя миграции вам придётся вручную выбрать внесённые изменения для выполнения следующей миграции. Откат к предыдущей точке до внесения каких-либо изменений в неудавшуюся миграцию невозможен.
  • Для большинства операций по изменению схемы MySQL полностью переписывает таблицы. В худшем случае время выполнения пропорционально количеству строк в таблице, в которые нужно добавить или удалить столбцы. Согласно документации Django, это может занять всего одну минуту на миллион строк.
  • В MySQL существуют небольшие ограничения на длину имён столбцов, таблиц и индексов. Также существует ограничение на общий размер всех столбцов и томов индексов. Хотя некоторые другие бэкенды поддерживают более высокие ограничения, установленные в Django, аналогичные индексы невозможно создать с помощью бэкенда MySQL.

Перед выбором любой базы данных для использования с Django обязательно взвесьте все «за» и «против».

Шаг 5 — Проверка схемы базы данных

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

Для этого выполните следующую команду в терминале для входа в MySQL.

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, выполните команду disable:

deactivate

Отключение среды разработки возвращает вас в командную строку терминала.

Результат

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

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Вам также может понравиться