1. NullBooleanField → BooleanField(null=True)
Из лекции (старое — Django 2.x/3.x)
# Поле для логического значения с возможностью NULL
# NullBooleanField — УСТАРЕЛО с Django 4.0, удалено в Django 5.x
is_active = models.NullBooleanField()
Современное (Django 5.x)
# Правильный способ хранить True/False/NULL
is_active = models.BooleanField(null=True, blank=True)
Почему изменили: NullBooleanField дублировал функцию обычного BooleanField(null=True). В Django 4.0 он объявлен устаревшим, в Django 5.x — удалён. Старый код вызовет ImproperlyConfigured при запуске.
2. ForeignKey без on_delete → on_delete обязателен
Из лекции (старое — до Django 2.0)
# В Django 1.x on_delete было необязательным (DEFAULT: CASCADE)
author = models.ForeignKey(Author)
Современное (Django 5.x)
# on_delete ОБЯЗАТЕЛЕН — нужно явно указать поведение
author = models.ForeignKey(Author, on_delete=models.CASCADE)
# Или другие варианты:
author = models.ForeignKey(Author, on_delete=models.PROTECT)
author = models.ForeignKey(Author, on_delete=models.SET_NULL, null=True)
Почему изменили: неявное поведение CASCADE приводило к случайному массовому удалению данных. Начиная с Django 2.0, параметр on_delete обязателен — ошибка TypeError возникает при запуске, если его не указать.
3. choices как список кортежей → TextChoices / IntegerChoices
Из лекции (старое, но работает)
# Список кортежей — работает и сейчас, но менее удобен
STATUS_CHOICES = [
('draft', 'Draft'),
('published', 'Published'),
]
status = models.CharField(max_length=10, choices=STATUS_CHOICES)
Современное (Django 3.0+)
# TextChoices — перечисление с автодополнением, защита от опечаток
class Status(models.TextChoices):
DRAFT = 'draft', 'Черновик'
PUBLISHED = 'published', 'Опубликовано'
status = models.CharField(
max_length=10,
choices=Status.choices,
default=Status.DRAFT
)
# Преимущество: использование констант вместо строк
if article.status == Status.PUBLISHED:
...
# вместо:
if article.status == 'published': # можно опечататься
...
Почему лучше: IDE даёт автодополнение, статический анализ ловит опечатки, код читается чище. Старый формат кортежей продолжает работать — это не ошибка, но TextChoices — best practice.
4. AutoField → BigAutoField (первичный ключ)
Из лекции (старое)
# В старых проектах и в лекции — AutoField (32-битный int)
# В settings.py явно не задавалось или:
DEFAULT_AUTO_FIELD = 'django.db.models.AutoField'
Современное (Django 3.2+ по умолчанию)
# Django 3.2+ использует BigAutoField по умолчанию
# В settings.py (уже стоит в новых проектах):
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
# BigAutoField — 64-битный, диапазон: 1 до 9,223,372,036,854,775,807
# Практически неограниченный счётчик записей
Почему изменили: 32-битный AutoField вмещает до ~2,1 млрд записей. Для высоконагруженных систем этого недостаточно. BigAutoField снимает это ограничение.
5. db_index на поле → Meta.indexes
Старый подход (лекция)
# db_index прямо на поле — работает
email = models.CharField(max_length=200, db_index=True)
Современный подход (составные индексы, именованные)
class Article(models.Model):
title = models.CharField(max_length=200)
author = models.CharField(max_length=100)
published_date = models.DateField()
class Meta:
# Простой индекс через Meta — более гибко
indexes = [
models.Index(fields=['author']),
# Составной индекс по нескольким полям
models.Index(fields=['author', 'published_date'], name='author_date_idx'),
]
Когда какой подход: db_index=True на поле — быстро и просто для одного поля. Meta.indexes — для составных индексов, именованных индексов и более тонкой настройки.
Итоговая таблица сравнений
| Из лекции (старое) | Django 5.x (современное) | Статус |
|---|---|---|
NullBooleanField() |
BooleanField(null=True) |
Удалено в 5.x |
ForeignKey(Model) без on_delete |
ForeignKey(Model, on_delete=CASCADE) |
Ошибка с 2.0 |
choices=[('a','A'),...] |
class Status(TextChoices) |
Работает, но устаревший стиль |
AutoField как pk |
BigAutoField (по умолчанию с 3.2) |
AutoField работает, но BigAutoField лучше |
db_index=True |
Meta.indexes для составных |
Оба работают, Meta гибче |