⚖️ Старый vs Новый API
⚡ Главные отличия
- Enum.choices vs TextChoices: лекция использует самописный Enum — современно через
models.TextChoices - deleted default=True: в лекции опечатка — логически должно быть
default=False - date_joined / registered: лекция переименовывает через
name="registered"— в Django 5.x это поддерживается, но нестандартно
Из лекции (старое)
# apps/users/choices/positions.py
from enum import Enum
class Positions(Enum):
CEO = "CEO"
CTO = "CTO"
PROGRAMMER = "Programmer"
...
@classmethod
def choices(cls):
return [(attr.name, attr.value) for attr in cls]
# В модели:
position = models.CharField(
max_length=15,
choices=UserPositions.choices, # вызов метода
default=UserPositions.PROGRAMMER
)
Современный подход (Django 5.x)
# apps/users/choices/positions.py
from django.db import models
class UserPositions(models.TextChoices):
CEO = "CEO", "CEO"
CTO = "CTO", "CTO"
PROGRAMMER = "PROGRAMMER", "Programmer"
DESIGNER = "DESIGNER", "Designer"
PRODUCT_OWNER = "PRODUCT_OWNER", "Product Owner"
PROJECT_OWNER = "PROJECT_OWNER", "Project Owner"
PROJECT_MANAGER = "PROJECT_MANAGER", "Project Manager"
QA = "QA", "QA"
# В модели:
position = models.CharField(
max_length=15,
choices=UserPositions, # без вызова .choices
default=UserPositions.PROGRAMMER
)
Почему лучше TextChoices: встроенная поддержка Django ORM (фильтрация, миграции), авто-генерация .choices, .values, .labels. Не нужен метод @classmethod choices().
Из лекции (возможная опечатка)
# В модели User:
deleted = models.BooleanField(default=True)
# Логика: новый пользователь сразу "удалён" —
# это не имеет смысла
Правильно
# В модели User:
deleted = models.BooleanField(default=False)
# Новый пользователь активен (не удалён)
# Soft-delete: при удалении → deleted=True,
# deleted_at=datetime.now()
Из лекции
# Переименование поля через name=
date_joined = models.DateTimeField(
name="registered", auto_now_add=True
)
# Обращение к полю: user.registered
Современный подход
# Явное именование поля
registered = models.DateTimeField(auto_now_add=True)
# или стандартное
date_joined = models.DateTimeField(auto_now_add=True)
# Подход через name= работает, но нестандартен
# и путает при миграциях
Из лекции (опечатка в Meta)
# apps/tasks/serializers
class CreateUpdateTaskSerializer(serializers.ModelSerializer):
...
class Meta:
model = Task
fields = (
'deadline',
'Assignee' # опечатка — с большой буквы
)
Правильно
class CreateUpdateTaskSerializer(serializers.ModelSerializer):
assignee = serializers.SlugRelatedField(
slug_field='email',
queryset=User.objects.all(),
required=False
)
class Meta:
model = Task
fields = (
'deadline',
'assignee', # строчная
# ... другие нужные поля
)