1. Choices: список кортежей → TextChoices
Из лекции (старое)
STATUSES_CHOICES = [
('New', 'New'),
('In_progress', 'In_progress'),
('Completed', 'Completed'),
('Closed', 'Closed'),
]
class Task(models.Model):
status = models.CharField(
max_length=15,
choices=STATUSES_CHOICES,
default='New'
)
Работает во всех версиях Django. Используется в практикуме.
Современное (Django 3+)
class Task(models.Model):
class Status(models.TextChoices):
NEW = 'New', 'New'
IN_PROGRESS = 'In_progress', 'In Progress'
COMPLETED = 'Completed', 'Completed'
CLOSED = 'Closed', 'Closed'
status = models.CharField(
max_length=15,
choices=Status.choices,
default=Status.NEW
)
Поддержка автодополнения, строгая типизация.
2. Регистрация в Admin
Из лекции (старое)
class ProjectAdmin(admin.ModelAdmin):
list_display = ['name']
admin.site.register(Project, ProjectAdmin)
Работает, но устарело.
Современное (рекомендуется)
@admin.register(Project)
class ProjectAdmin(admin.ModelAdmin):
list_display = ['name']
Декоратор — стандарт с Django 1.7.
3. Admin-действия: for obj + save() → queryset.update()
Из лекции (из практикума)
def change_status(self, request, objects):
for obj in objects:
obj.status = 'Closed'
obj.save()
return objects
N запросов к БД (по одному на объект). Параметр называется queryset по конвенции.
Современное (эффективно)
def change_status(self, request, queryset):
queryset.update(status='Closed')
# Один SQL UPDATE запрос
Один запрос к БД. Рекомендуется для массовых операций.
⚠️ Важно: при
queryset.update() не вызываются save() и сигналы post_save. Если у модели есть логика в save() — используйте цикл с obj.save().
4. unique_together → UniqueConstraint
Из лекции (устаревшее)
class Meta:
unique_together = (('title', 'project'),)
Работает, но помечено deprecated в Django 4.2.
Современное (Django 4.x+)
from django.db.models import UniqueConstraint
class Meta:
constraints = [
UniqueConstraint(
fields=['title', 'project'],
name='unique_task_in_project'
)
]
Более гибко, поддерживает условные ограничения.
5. ManyToManyField: null=True → только blank=True
Из лекции (неверно)
tags = models.ManyToManyField(
'Tag',
null=True, # ← Django игнорирует это!
blank=True,
related_name='tasks'
)
Django выдаёт SystemCheck warning: null=True не имеет смысла для M2M.
Современное (правильно)
tags = models.ManyToManyField(
'Tag',
blank=True, # ← только blank=True
related_name='tasks'
)
Для M2M "пустое" означает отсутствие записей в промежуточной таблице. null=True не нужен.