Ответ
Наследование моделей в 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())