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;
Преимущества миграций
- Управление изменениями: легко отслеживать и применять изменения структуры БД.
- Безопасность данных: изменения без потери существующих данных.
- Синхронизация с моделями: соответствие между моделями и таблицами в БД.
Механизм работы миграций (подробно)
- Обнаружение изменений:
makemigrationsсканируетmodels.pyи сравнивает с предыдущими миграциями. - Создание файла миграции: Python-скрипт в папке
migrations/с уникальным именем (0001_initial.py). - Запуск и определение необходимых миграций:
migrateсверяется с таблицейdjango_migrations. - Применение к БД: Django генерирует SQL и выполняет его через драйвер БД (psycopg2, sqlite3 и т.д.).
- Обновление таблицы миграций: добавляет запись о применённой миграции в
django_migrations. - Обработка ошибок и откатов: при ошибке Django откатывает изменения через транзакции.
4. Админка Django
Регистрация модели в Admin
Два шага: импорт и регистрация через admin.site.register():
# myapp/admin.py
from django.contrib import admin
from .models import Book
admin.site.register(Book)
Что происходит при регистрации:
- Django создаёт стандартный класс AdminModel для модели Book.
- Появляется страница списка объектов (таблица всех записей).
- Появляются страницы создания и редактирования объектов.
- В меню панели добавляется раздел для модели.
Создание суперпользователя
# Шаг 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 | Только буквы, цифры, дефис, подчёркивание |
URLField | URL-адреса | Валидирует формат 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 |
Поля для логических значений
| Поле | Описание | Примечание |
|---|---|---|
BooleanField | True или False | Актуальное поле Django 5.x |
NullBooleanField | True, 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 | Путь к файлу в файловой системе |
GenericIPAddressField | IP-адреса (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'