📖 Теория: Работа с моделями Django

⚡ Кратко

Модель Django — класс, унаследованный от models.Model, описывающий таблицу в БД. ORM автоматически генерирует SQL-запросы.

  • Определение модели → makemigrationsmigrate
  • Django автоматически добавляет поле id (BigAutoField) как первичный ключ
  • Поля модели — атрибуты класса, соответствующие столбцам таблицы
  • ForeignKey, ManyToManyField, OneToOneField — связи между моделями
  • Admin: admin.site.register(Model) + суперпользователь

Параметры полей: null (NULL в БД), blank (пустой в форме), choices, default, unique, verbose_name, help_text, db_index, validators.

1. Что такое модель Django

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

Модели являются центральной частью приложения Django: они позволяют работать с данными в удобной объектно-ориентированной форме, не писать SQL-запросы вручную.

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

Зачем нужны модели

  • Определение структуры данных: модели определяют, какие данные будут храниться и как они структурированы.
  • Управление данными: легко выполнять CRUD-операции (создание, чтение, обновление, удаление).
  • Валидация данных: встроенные правила валидации (обязательные поля, уникальные значения и т.д.).

Преимущества моделей Django

  • Упрощённая работа с базой данных: абстракция над SQL, снижает количество ошибок.
  • Автоматическая генерация SQL-запросов: Django генерирует нужные запросы самостоятельно.
  • Целостность и консистентность данных: валидация и связи между моделями.
  • Удобная миграция данных: система миграций позволяет изменять структуру БД без потери данных.
  • Интеграция с админкой Django: модели автоматически интегрируются с Admin-панелью.

2. Создание модели

Модель в Django создаётся как класс, наследуемый от models.Model. Каждый атрибут класса — поле таблицы.

from django.db import models

class Book(models.Model):
    title = models.CharField(max_length=200)
    author = models.CharField(max_length=100)
    published_date = models.DateField()

Из чего состоит модель:

  • Импорт модулей: в начале файла импортируется from django.db import models.
  • Определение класса модели: класс, наследующийся от models.Model.
  • Определение полей: атрибуты класса со своими типами и параметрами.

Сопоставление с базой данных

Django ORM автоматически создаёт таблицу и маппирует поля на столбцы:

  • CharField(max_length=200) → столбец title VARCHAR(200)
  • CharField(max_length=100) → столбец author VARCHAR(100)
  • DateField() → столбец published_date DATE

Django автоматически добавляет поле id (BigAutoField) как первичный ключ — если вы не задали его вручную.

3. Механизм определения моделей и миграции

Django определяет модели по наследованию: любой класс, унаследованный от models.Model, сканируется и обрабатывается как модель БД.

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

Создание миграций

После создания или изменения модели нужно создать миграцию:

python manage.py makemigrations

Команда сканирует models.py всех приложений из INSTALLED_APPS, сравнивает с предыдущими миграциями и создаёт файл в папке migrations/:

Migrations for 'first_app':
  first_app\migrations\0001_initial.py
    - Create model Book

Применение миграций

python manage.py migrate

Django проверяет таблицу django_migrations, определяет не применённые миграции и выполняет их последовательно, генерируя SQL-запросы:

BEGIN;
-- Create model Book
CREATE TABLE "myapp_book" (
    "id" serial NOT NULL PRIMARY KEY,
    "title" varchar(200) NOT NULL,
    "author" varchar(100) NOT NULL,
    "published_date" date NOT NULL
);
COMMIT;

Преимущества миграций

  • Управление изменениями: легко отслеживать и применять изменения структуры БД.
  • Безопасность данных: изменения без потери существующих данных.
  • Синхронизация с моделями: соответствие между моделями и таблицами в БД.

Механизм работы миграций (подробно)

  1. Обнаружение изменений: makemigrations сканирует models.py и сравнивает с предыдущими миграциями.
  2. Создание файла миграции: Python-скрипт в папке migrations/ с уникальным именем (0001_initial.py).
  3. Запуск и определение необходимых миграций: migrate сверяется с таблицей django_migrations.
  4. Применение к БД: Django генерирует SQL и выполняет его через драйвер БД (psycopg2, sqlite3 и т.д.).
  5. Обновление таблицы миграций: добавляет запись о применённой миграции в django_migrations.
  6. Обработка ошибок и откатов: при ошибке Django откатывает изменения через транзакции.

4. Админка Django

Полезно знать — Админка: предоставляет веб-интерфейс для управления данными в моделях. Позволяет просматривать, добавлять, изменять и удалять записи без написания кода или использования SQL.

Регистрация модели в Admin

Два шага: импорт и регистрация через admin.site.register():

# myapp/admin.py
from django.contrib import admin
from .models import Book

admin.site.register(Book)

Что происходит при регистрации:

  • Django создаёт стандартный класс AdminModel для модели Book.
  • Появляется страница списка объектов (таблица всех записей).
  • Появляются страницы создания и редактирования объектов.
  • В меню панели добавляется раздел для модели.

Создание суперпользователя

Суперпользователь обладает полными правами доступа ко всем разделам Admin и может просматривать, добавлять, изменять и удалять любые объекты.
# Шаг 1: Создать суперпользователя
python manage.py createsuperuser
# Вводим: username, email, password

# Шаг 2: Запустить сервер
python manage.py runserver

# Шаг 3: Открыть браузер
# http://127.0.0.1:8000/admin/

5. Поля в моделях Django

Поля в моделях — атрибуты класса, соответствующие столбцам в таблице. Они определяют тип данных, правила валидации и дополнительное поведение.

Строковые поля

ПолеОписаниеОсобенности
CharFieldКороткие строки (до 255 символов)Требует max_length
TextFieldДлинные текстыTEXT в SQL, max_length не обязателен
EmailFieldАдреса электронной почтыВалидирует формат email
SlugField«Слаг» — метка для URLТолько буквы, цифры, дефис, подчёркивание
URLFieldURL-адресаВалидирует формат URL

Числовые поля

ПолеОписаниеДиапазон
IntegerFieldЦелые числа−2,147,483,648 до 2,147,483,647
BigIntegerFieldБольшие целые числа±9,223,372,036,854,775,807
PositiveIntegerFieldПоложительные целые0 до 2,147,483,647
SmallIntegerFieldНебольшие целые числа−32768 до 32767
PositiveSmallIntegerFieldНебольшие положительные0 до 32767
FloatFieldЧисла с плавающей запятойdouble precision в SQL
DecimalFieldДесятичные с фиксированной точностьюТребует max_digits, decimal_places
BigAutoFieldАвтоинкремент (большой диапазон)По умолчанию первичный ключ
AutoFieldАвтоинкремент (обычный диапазон)Устаревший в пользу BigAutoField

Поля для логических значений

ПолеОписаниеПримечание
BooleanFieldTrue или FalseАктуальное поле Django 5.x
NullBooleanFieldTrue, False или NULLУстарело; используйте BooleanField(null=True)

Поля для дат и времени

ПолеОписаниеПолезные параметры
DateFieldДата (без времени)auto_now, auto_now_add
TimeFieldВремя (без даты)auto_now, auto_now_add
DateTimeFieldДата и времяauto_now, auto_now_add
DurationFieldВременные промежуткиХранит timedelta

Поля для связей между моделями

ПолеСвязьОбязательный параметр
ForeignKeyМногие к одному (N:1)on_delete
ManyToManyFieldМногие ко многим (N:M)
OneToOneFieldОдин к одному (1:1)on_delete

Прочие поля

ПолеОписание
FileFieldЗагрузка и хранение файлов
ImageFieldЗагрузка и хранение изображений (требует Pillow)
FilePathFieldПуть к файлу в файловой системе
GenericIPAddressFieldIP-адреса (IPv4 или IPv6)
UUIDFieldУникальные идентификаторы UUID
BinaryFieldБинарные данные

6. Общие параметры полей

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

null

Указывает, может ли поле содержать NULL в базе данных. По умолчанию False.

models.CharField(max_length=100, null=True)

blank

Указывает, может ли поле быть пустым в формах. По умолчанию False. Если True — поле не обязательно для заполнения в формах.

models.CharField(max_length=100, blank=True)
Важно: null=True — разрешает NULL в базе данных. blank=True — разрешает пустое значение в форме Django. Это разные вещи! Для строковых полей рекомендуется использовать blank=True без null=True — пустая строка лучше, чем NULL.

choices

Ограничивает возможные значения поля определённым набором вариантов.

STATUS_CHOICES = [
    ('draft', 'Черновик'),
    ('published', 'Опубликовано'),
]
status = models.CharField(max_length=10, choices=STATUS_CHOICES)

В Django 3.0+ можно использовать перечисления (IntegerChoices, TextChoices):

class Status(models.TextChoices):
    DRAFT = 'draft', 'Черновик'
    PUBLISHED = 'published', 'Опубликовано'

status = models.CharField(max_length=10, choices=Status.choices, default=Status.DRAFT)

default

Определяет значение по умолчанию для поля, если оно не задано при создании объекта.

models.CharField(max_length=100, default='N/A')

primary_key

Определяет, что это поле является первичным ключом таблицы. Если не задано — Django автоматически добавляет поле id (BigAutoField).

models.CharField(primary_key=True)

unique

Указывает, что значения в поле должны быть уникальными. По умолчанию False.

models.CharField(max_length=100, unique=True)

verbose_name

Определяет читаемое имя для поля, используемое в Admin и формах.

models.CharField(max_length=100, verbose_name='Полное имя')

help_text

Вспомогательный текст для поля, отображающийся в Admin и формах.

models.CharField(max_length=100, help_text='Введите полное имя пользователя')

db_index

Создаёт индекс для поля в базе данных. Ускоряет поиск по этому полю. По умолчанию False.

models.CharField(max_length=100, db_index=True)

editable

Определяет, можно ли редактировать поле в Admin и формах. По умолчанию True.

models.CharField(max_length=100, editable=False)

error_messages

Определяет пользовательские сообщения об ошибках для поля.

models.CharField(
    max_length=100,
    error_messages={
        'blank': 'Это поле не может быть пустым.',
        'unique': 'Это значение уже используется.'
    }
)

validators

Список валидаторов для проверки значений поля.

from django.core.validators import MinLengthValidator

models.CharField(
    max_length=100,
    validators=[MinLengthValidator(2)]
)

unique_for_date, unique_for_month, unique_for_year

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

# Значение unique в пределах одной даты publish_date
models.CharField(max_length=100, unique_for_date='publish_date')

# Значение unique в пределах одного месяца
models.CharField(max_length=100, unique_for_month='publish_month')

# Значение unique в пределах одного года
models.CharField(max_length=100, unique_for_year='publish_year')

7. Полный пример модели

Итоговая модель, демонстрирующая основные возможности:

from django.db import models
from django.core.validators import MinLengthValidator


class Book(models.Model):
    """Модель книги с демонстрацией различных полей и параметров."""

    # CharField с параметрами
    title = models.CharField(
        max_length=200,
        verbose_name='Название',
        unique=True,
        help_text='Введите название книги'
    )
    # TextField для длинного текста
    description = models.TextField(
        blank=True,
        null=True,
        verbose_name='Описание'
    )
    # DecimalField для денег
    price = models.DecimalField(
        max_digits=8,
        decimal_places=2,
        default=0.00,
        verbose_name='Цена'
    )
    # DateField с автозаполнением
    published_date = models.DateField(
        verbose_name='Дата публикации',
        null=True,
        blank=True
    )
    # BooleanField
    in_stock = models.BooleanField(
        default=True,
        verbose_name='В наличии'
    )
    # choices с TextChoices (современный Django 5.x подход)
    class Genre(models.TextChoices):
        FICTION = 'fiction', 'Художественная'
        NON_FICTION = 'non_fiction', 'Нехудожественная'
        SCIENCE = 'science', 'Научная'

    genre = models.CharField(
        max_length=20,
        choices=Genre.choices,
        default=Genre.FICTION,
        verbose_name='Жанр'
    )
    # CharField с валидатором
    isbn = models.CharField(
        max_length=13,
        unique=True,
        validators=[MinLengthValidator(10)],
        verbose_name='ISBN',
        help_text='10 или 13 символов'
    )
    # Авто-дата создания
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return f"{self.title} ({self.published_date})"

    class Meta:
        verbose_name = 'Книга'
        verbose_name_plural = 'Книги'
        ordering = ['-published_date']
        db_table = 'library_books'