Django Models - попытка получить "лучшее из двух миров", когда дело доходит до копирования модели против ее подклассификации

Допустим, у меня есть базовый класс (модель Django) под названием Character, который выглядит примерно так

class Character(models.Model):
    strength = models.blabla
    dex = models.blabla
    ...

Я могу установить его атрибуты и подключить к Admin, и все будет прекрасно.

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

Вариант 1:

# The basic obvious stupid-simple answer is just to copy the model and add the fields

class NonPlayerCharacter(models.Model):
    strength = models.blabla
    dex = models.blabla
    ...
    faction = models.blabla

Плюсы: Все очень просто и легко управляется, а если в будущем модели будут расходиться, это тоже не составит труда.

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

Вариант 2:

# The next most obvious solution is to subclass Character

class NonPlayerCharacter(Character):
    faction = models.blabla

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

Минусы: Везде, где я запрашиваю Character, по умолчанию также будут выведены все подклассы Character. Я (в некоторой степени) знаю, как отфильтровать это в каждом конкретном запросе, но было бы здорово, если бы Character.objects просто получал персонажей, а все остальное оставлял на усмотрение запросов для конкретной модели/подкласса.

Есть ли удобный метод, позволяющий получить лучшее из обоих миров, не фильтруя Character каждый раз, или я просто прошу чего-то неразумного?

Обычно вы можете сделать абстрактную базовую модель, например:

class BaseCharacter(models.Model):
    strength = models.blabla
    dex = models.blabla
    …

    class Meta:
        abstract = True


class Character(BaseCharacter):
    pass


class NonPlayerCharacter(BaseCharacter):
    faction = models.blabla
Вернуться на верх