⚖️ Старый vs Новый: паттерны Django-моделей

Устаревший код из лекции → современный Django 5.x

⚡ Главные изменения

  • NullBooleanFieldBooleanField(null=True)
  • class Config в модели → class Meta
  • Регистрация в Admin: admin.site.register(Model)@admin.register(Model)
  • ForeignKey без on_delete (Django 1.x) → обязателен с Django 2.0+
  • Строковый choices → список кортежей [('val', 'label'), ...]
Материалы практикума написаны в базовом современном стиле Django 3.x–5.x. Ниже собраны типичные паттерны, которые встречаются в старых проектах и учебниках.

1. NullBooleanField (устарел)

Из лекции (старое):

# Django 2.x / 3.x
class Author(models.Model):
    deleted = models.NullBooleanField()

Современное (Django 4.x+):

# Django 4.x / 5.x
class Author(models.Model):
    deleted = models.BooleanField(
        default=False,
        null=True  # если нужно три значения
    )

В Django 4.0 NullBooleanField официально устарел и удалён в 4.2.

2. on_delete в ForeignKey — обязателен с Django 2.0

Из лекции (старое, Django 1.x):

class Book(models.Model):
    author = models.ForeignKey(Author)
    # Нет on_delete — работало в Django 1.x

Современное (Django 2.0+):

class Book(models.Model):
    author = models.ForeignKey(
        Author,
        on_delete=models.SET_NULL,  # ОБЯЗАТЕЛЬНО
        null=True
    )

3. Регистрация в Admin

Из лекции (простая регистрация):

# admin.py
from .models import Author
admin.site.register(Author)

Современное (с настройками):

# admin.py
from django.contrib import admin
from .models import Author

@admin.register(Author)
class AuthorAdmin(admin.ModelAdmin):
    list_display = ('first_name', 'last_name')
    search_fields = ('last_name',)
    list_filter = ('deleted',)

4. Choices — строковый стиль vs кортежи

Старый паттерн:

GENDER_MALE = 'Male'
GENDER_FEMALE = 'Female'
GENDER_CHOICES = (
    (GENDER_MALE, 'Мужской'),
    (GENDER_FEMALE, 'Женский'),
)

Современное (Django 3.0+):

# Вариант 1: список кортежей (из практикума)
GENDER_CHOICES = [
    ('Male', 'Мужской'),
    ('Female', 'Женский'),
    ('Other', 'Другой'),
]

# Вариант 2: TextChoices (Django 3.0+)
class GenderChoices(models.TextChoices):
    MALE = 'Male', 'Мужской'
    FEMALE = 'Female', 'Женский'
    OTHER = 'Other', 'Другой'

5. Meta: verbose_name и ordering

Без Meta (из базовых примеров лекции):

class Author(models.Model):
    first_name = models.CharField(max_length=100)
    last_name = models.CharField(max_length=100)
    # Admin показывает: "Author object (1)"

С Meta и __str__ (рекомендуемо):

class Author(models.Model):
    first_name = models.CharField(max_length=100)
    last_name = models.CharField(max_length=100)

    class Meta:
        verbose_name = "Автор"
        verbose_name_plural = "Авторы"
        ordering = ['last_name']

    def __str__(self):
        return f"{self.first_name} {self.last_name[0]}."

6. ManyToManyField — EventParticipant.member

В материалах лекции у EventParticipant поле member объявлено как ManyToManyField. Это создаёт дополнительную промежуточную таблицу. Обычно для «участник зарегистрирован на событие» используют ForeignKey (один участник — одна запись). Вариант с ManyToManyField был выбран в лекции — он используется как есть. ⚠️ Проверить по документации

7. DateField vs DateTimeField для событий

Из лекции (задача 15):

class Event(models.Model):
    date = models.DateField()
    # Только дата, без времени

Современная рекомендация:

class Event(models.Model):
    date = models.DateTimeField()
    # Дата И время события — логичнее для событий
    # В задаче 15 указано "и дата, и время"
    # → используйте DateTimeField

В задаче 15 формулировка: «Дата проведения события: и дата, и время». Однако в решении из лекции используется DateField. Правильно использовать DateTimeField.