Какие типы наследования моделей существуют в Django

Ответ

Наследование моделей в Django — это механизм, позволяющий создавать новые модели на основе существующих, переиспользуя их поля и методы в соответствии с принципом DRY (Don't Repeat Yourself). Существует три основных типа наследования:

1. Абстрактное наследование (Abstract base classes)

Используется, когда нужно создать общий набор полей и методов для нескольких моделей, но при этом не требуется создавать отдельную таблицу в базе данных для родительской модели.

  • Как работает: Родительская модель помечается как абстрактная с помощью class Meta: abstract = True.
  • Результат: Поля родительской модели копируются в дочерние. Таблица создается только для дочерних моделей.

Пример:

from django.db import models

# Для этой модели таблица создана не будет
class CommonInfo(models.Model):
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        abstract = True

# Модель Post унаследует поля created_at и updated_at
class Post(CommonInfo):
    title = models.CharField(max_length=100)

2. Многотабличное наследование (Multi-table inheritance)

Применяется, когда дочерняя модель является специализированной версией родительской и имеет собственные поля. Каждая модель получает свою таблицу в базе данных.

  • Как работает: Django автоматически создает связь OneToOneField от дочерней модели к родительской.
  • Результат: Создаются таблицы для обеих моделей. При запросе к дочерней модели Django выполняет JOIN для получения данных из обеих таблиц.

Пример:

from django.db import models

class Place(models.Model):
    name = models.CharField(max_length=50)
    address = models.CharField(max_length=80)

# Restaurant является подтипом Place
class Restaurant(Place):
    serves_pizza = models.BooleanField(default=False)

3. Прокси-модели (Proxy models)

Используются для изменения Python-поведения модели (например, добавления новых методов, изменения менеджера по умолчанию или порядка сортировки), не затрагивая ее поля или схему базы данных.

  • Как работает: Модель помечается как прокси с помощью class Meta: proxy = True.
  • Результат: Новая модель работает с той же таблицей в БД, что и родительская.

Пример:

# Используем модель Post из первого примера
class OrderedPost(Post):
    class Meta:
        proxy = True
        ordering = ['-created_at'] # Изменяем сортировку по умолчанию

    def get_word_count(self):
        return len(self.title.split())