Django: следование за отношениями "назад" с несколькими моделями

У меня есть набор моделей, похожих на эту, где и Роман и Журнал имеют ForeignKey к Книжной полке:

class Bookshelf(models.Model):
    name = models.TextField()

class Novel(models.Model):
    bookshelf = models.ForeignKey(Bookshelf)

class Magazine(models.Model):
    bookshelf = models.ForeignKey(Bookshelf)

Следуя отношениям назад в соответствии с docs, я знаю, что могу использовать два Managers: bookshelf.novel_set и bookshelf.magazine_set.

Но как лучше всего разместить на книжной полке один комплект романов и журналов? Моя реальная установка имеет растущий список моделей, подобных этой. Выполнение одних и тех же операций для многих "_наборов" кажется непитоничным и слишком много шаблонов.

Я рассматривал GenericRelation и написание пользовательского Manager, но ни то, ни другое, кажется, не делает то, что мне нужно чисто (я могу ошибаться). Использую Django 3.2.

Каждая модель сопоставляется с одной таблицей БД. Что является ограничительным.

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

class BookshelfItem( models.Model)
    NOVEL = 'Novel'
    MAGAZINE = 'Magazine'
    BOOKSHELF_ITEM_TYPES = ( (NOVEL, 'Novel'), (MAGAZINE, 'Magazine'), )

    item_type = models.CharField( choices = BOOKSHELF_ITEM_TYPES, ...)
    bookshelf = models.ForeignKey(Bookshelf, related_name='items')
    ...

Теперь вы можете получить список обоих с помощью bookshelf.items и список выбранного с помощью bookshelf.items.filter( item_type = BookShelfItem.MAGAZINE ). Вы можете даже определить больше менеджеров на модели Bookshelf, чтобы сделать возможным Bookshelf.magazines.filter(...) и т.д.

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

Вернуться на верх