Элегантное распространение одной модели Django по нескольким таблицам?

Существует множество документов и обсуждений для того, чтобы несколько моделей имели общие поля в родительском классе/таблице, используя "конкретное" или "многотабличное" наследование:

class Place(models.Model):
    ...

class Restaurant(Place):
    ...

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

Рассмотрим следующий сценарий:

class Person_Profile(models.Model):
    ...lots of fields...

class Person_Preferences(models.Model):
    ...lots of fields...

class Person(Person_Profile, Person_Preferences):
    ...small set of core fields...
<
  • Когда вы создаете Person, два других объекта автоматически создаются и связываются для вас.
  • Вы можете получить доступ к полям профиля и предпочтений непосредственно в Person. (person.some_field)

Единственное, чего мне не хватает, это как элегантно контролировать, когда Django загружает поля из родительской таблицы, поскольку в настоящее время загрузка Person с помощью p = Person.objects.first() приводит к тому, что все три таблицы объединяются и выбираются по умолчанию.

Splitted model - Это хорошее решение, только если вы не понимаете идею DataManagers/Queryset.

Разделение полей на модели - хороший подход, если вы используете Meta.abstract = True. Если вы создаете два реальных класса только для того, чтобы сложить все поля в дочернем классе - вы теряете много времени с джойнами на каждый запрос в БД.

больше здесь: https://docs.djangoproject.com/en/4.1/topics/db/models/#abstract-base-classes

В QuerySet вы можете определить множество методов. После этого вы можете соединить методы в цепочку.

class Person_Profile(models.Model):
    Meta:
        abstract = True

    ...lots of fields...

class Person_Preferences(models.Model):
    Meta:
        abstract = True

    ...lots of fields...

class Person(Person_Profile, Person_Preferences):
    ...small set of core fields...
    objects = PersonQueryset.as_manager()  # in old django PersonDataManager()

Как может выглядеть PersonDataManager или PersonQuerySet:

class PersonQuerySet(QuerySet):

    def onlySpecialFields(self, *args, **kwargs):
        return self.only(*my_special_only_list)

    def deferSpecialFields(self, *args, **kwargs):
        return self.defer(*my_special_defer_list)

    def skinnyPersons(self, *args, **kwargs):
        return self.only('name')

Как вы можете его использовать:

SkinnyPersons_List = Person.objects.filter(name=something).skinnyPersons()
# after that
FirstSkinnyPerson = SkinnyPersons_List.first()

# somethere in code
LastSkinnyPerson = Person.objects.skinnyPersons().last()

Плюсы:

  • тип содержимого всегда один и тот же
  • у вас нет проблем с родовыми объектами
  • вы работаете с одинаковыми ._meta, .app_label и .model_name
  • у вас нет новой модели, которая вам не нужна
  • .
  • вы используете идею django querysets

конс:

  • не найдено
Вернуться на верх