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

Введение

В предыдущем руководстве “Как создать приложение Django и подключить его к базе данных” мы рассмотрели, как создать базу данных MySQL, как создать и запустить приложение Django и как подключить его к базе данных MySQL.

В этом руководстве мы создадим модели Django, которые определяют поля и поведение данных приложения Blog, которые мы будем хранить. Эти модели отображают данные из вашего приложения Django в базу данных. Это то, что Django использует для генерации таблиц базы данных через свой API отображения объектов в отношения, называемый “моделями”.

Необходимые условия

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

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

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

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

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

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

  1. cd ~/my_blog_app
  2. . env/bin/activate
  3. cd blog

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

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

  1. cd ~/my_blog_app/blog/blogsite

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

  1. cat models.py

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

models.py
from django.db import models

# Создайте свои модели здесь.

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

  1. nano models.py

Внутри этого файла код для импорта API моделей уже добавлен, мы можем удалить комментарий, который следует за ним. Затем мы импортируем slugify для создания слагов из строк, User из Django для аутентификации и reverse из django.urls для большей гибкости в создании URL.

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

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

models.py
...
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 и функцию для сохранения поста. Это крайне важно, потому что это создает уникальную ссылку для соответствия нашему уникальному посту.

models.py
...
    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 обычно содержит другую важную логику модели, не связанную с определением полей базы данных.

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

        def __unicode__(self):
            return self.title

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

  • name — Имя человека, размещающего комментарий.
  • email — Адрес электронной почты человека, оставившего комментарий.
  • text — Текст самого комментария.
  • post — Пост, к которому был оставлен комментарий.
  • created_on — Время создания комментария.
models.py
...
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 соответствует следующему:

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.

  1. cd ~/my_blog_app/blog/blog

Откройте ваш файл settings.py, например, с помощью nano.

  1. nano settings.py

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

settings.py
# Определение приложений
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, например:

  1. cd ~/my_blog_app/blog

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

  1. 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? Если теперь вернуться в этот каталог при помощи команды cd, мы заметим, что добавлены два элемента: __pycache__ и 0001_initial.py. Файл 0001_initial.py был автоматически создан, когда вы выполнили команду makemigrations. Подобный файл будет создаваться каждый раз при выполнении команды makemigrations.

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

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

  1. cd ~/my_blog_app/blog

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

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

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

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

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

  1. python manage.py migrate

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

Output
Operations 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, который мы создали в предыдущем уроке.

  1. mysql blog_data -u djangouser

Теперь выберите нашу базу данных blog_data. Если вы не знаете, какую базу данных вы используете, вы можете показать все базы данных с помощью SHOW DATABASES; в SQL.

  1. USE blog_data;

Затем введите следующую команду для просмотра таблиц.

  1. 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. Это модели, которые мы только что создали. Давайте проверим, содержат ли они поля, которые мы определили.

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

  1. deactivate

Отключение вашей среды программирования вернет вас к приглашению командного терминала.

Заключение

{
“error”: “Upstream error…”
}

Source:
https://www.digitalocean.com/community/tutorials/how-to-create-django-models