⚖️ Старый vs Новый: устаревшие паттерны Django
⚡ Ключевые изменения
- index_together → indexes — index_together считается устаревшим; используй models.Index в indexes.
- unique_together → UniqueConstraint — предпочтительный современный способ.
- admin.site.register → @admin.register — декоратор удобнее и более Pythonic.
- actions как функции → methods — в Django 5.x действия оформляются как методы ModelAdmin.
- get_or_create / update_or_create — используй вместо ручных try/except при частом паттерне.
1. index_together → indexes (устарело в Django 4.2)
Из лекции (старое): использовался
index_together.
# СТАРЫЙ СПОСОБ (из лекции) — устарело
class Meta:
index_together = ('title', 'author')
# СОВРЕМЕННЫЙ СПОСОБ — Django 5.x
class Meta:
indexes = [
models.Index(fields=['title', 'author']),
models.Index(fields=['published_date'], name='published_idx'),
]
Почему: indexes гибче — поддерживает именованные индексы, частичные индексы, тип индекса и другие параметры. index_together объявлен устаревшим и будет удалён в будущем.
2. unique_together → UniqueConstraint (рекомендовано с Django 2.2)
Из лекции (старое):
unique_together в классе Meta.
# СТАРЫЙ СПОСОБ (из лекции) — ещё работает, но устарело
class Meta:
unique_together = ('title', 'author')
# СОВРЕМЕННЫЙ СПОСОБ — Django 5.x
from django.db.models import UniqueConstraint
class Meta:
constraints = [
UniqueConstraint(fields=['title', 'author'], name='unique_title_author'),
]
Почему: UniqueConstraint поддерживает условные (partial) ограничения и именование, что важно для миграций и консистентности на уровне БД.
3. admin.site.register → @admin.register
Из лекции: оба способа показаны. Декоратор предпочтителен.
# СТАРЫЙ СПОСОБ (из лекции — способ 1)
class BookAdmin(admin.ModelAdmin):
list_display = ('title', 'author')
admin.site.register(Book, BookAdmin)
# СОВРЕМЕННЫЙ СПОСОБ (из лекции — способ 2, рекомендуется)
@admin.register(Book)
class BookAdmin(admin.ModelAdmin):
list_display = ('title', 'author')
Почему: декоратор связывает класс и модель в одном месте, исключает возможность забыть вызов register.
4. Action как глобальная функция → метод ModelAdmin
Из лекции (старое): action определялся как отдельная функция вне класса.
# СТАРЫЙ СПОСОБ (из лекции)
def update_created_at(modeladmin, request, queryset):
queryset.update(created_at=timezone.now())
update_created_at.short_description = "Update created_at to current time"
class BookAdmin(admin.ModelAdmin):
actions = [update_created_at]
# СОВРЕМЕННЫЙ СПОСОБ — Django 5.x (метод класса)
@admin.register(Book)
class BookAdmin(admin.ModelAdmin):
actions = ['update_created_at']
@admin.action(description="Update created_at to current time")
def update_created_at(self, request, queryset):
queryset.update(created_at=timezone.now())
Почему: декоратор @admin.action появился в Django 3.2. Метод класса лучше инкапсулирует логику, а @admin.action(description=...) заменяет присвоение short_description.
5. Ручная обработка get() → get_or_create / update_or_create
# СТАРЫЙ СПОСОБ — много кода
try:
obj = Book.objects.get(title="The Great Gatsby")
except Book.DoesNotExist:
obj = Book.objects.create(title="The Great Gatsby", author="Fitzgerald", published_date="1925-04-10")
# СОВРЕМЕННЫЙ СПОСОБ
obj, created = Book.objects.get_or_create(
title="The Great Gatsby",
defaults={"author": "Fitzgerald", "published_date": "1925-04-10"}
)
Почему: get_or_create атомарен (использует SELECT + INSERT в транзакции) и исключает дублирование кода.