Wagtail CMS: поиск всех страниц, имеющих отношение к текущей странице

Я пытаюсь понять, как получить ссылки на все страницы моего сайта, на которых просматриваемая в данный момент страница указана как связанная страница с помощью ParentalKey modelcluster.

Базовая настройка выглядит следующим образом:

# RelatedLink inherits from LinkFields, 
# both directly copied from the wagtaildemo project

class ParentPageRelatedLink(Orderable, RelatedLink):
    page = ParentalKey('ParentPage', related_name='related_links')


class ParentPage(Page):
    parent_page_types = ['ParentPage']
    subpage_types = ['ParentPage', 'ChildPage']

    def child_pages(self):
        children = ChildPage.objects.live().descendant_of(self)
        return children

ParentPage.content_panels = [
    FieldPanel('title', classname="full title"),
    FieldPanel('body', classname="full"),
    InlinePanel(ParentPage, 'related_links', label="Related links"),
]


class ChildPage(Page):
    parent_page_types = ['ParentPage']
    parent_page_types = ['ChildPage']

    def parent_index(self):
        return self.get_ancestors().type(ParentPage).last()

ChildPage.content_panels = [
    FieldPanel('title', classname="full title"),
    FieldPanel('body', classname="full"),
    InlinePanel(ChildPage, 'related_links', label="Related links"),
]

Если все правильно понять, чтобы получить каждую ParentPage, которая имеет текущую ChildPage в своих связанных_ссылках, мне нужно будет просмотреть каждую страницу, указанную в ChildPage.parent_page_types, проверить, находится ли текущая ChildPage в ParentPage.related_links, а затем вывести все, что я нужно от каждой из этих ParentPages.

Похоже, что было бы много запросов к базе данных, если бы было много экземпляров типов страниц, перечисленных в parent_page_types.

Есть ли способ лучше?

Например, разрешает ли modelcluster какие-либо обратные ссылки (например, то, что Flask-SQLAlchemy предоставляет при использовании db.relashionship(backref="something")) через ParentalKey, созданный в ParentPageRelatedLink? Это не похоже на проверку таблиц базы данных.

Изменить

Итак, похоже, что related_name из LinkFields может быть способом сделать это, но поскольку я не могу установить что-то вроде «related_from», поскольку LinkFields наследуется многими различными классами, подобными ParentPage, кажется, что я должен иметь отдельные классы LinkField с собственными уникальными определениями ForeignKey(related_name="something") для каждой ParentPage... Или действуйте, как указано в документации по django. Но тогда я мог бы быть лучше с моей первоначальной мыслью о петле?

class LinkFields(models.Model):
    link_external = models.URLField("External link", blank=True)
    link_page = models.ForeignKey(
        'wagtailcore.Page',
        null=True,
        blank=True,
        related_name='+'
    )
    link_document = models.ForeignKey(
        'wagtaildocs.Document',
        null=True,
        blank=True,
        related_name='+'
    )

    @property
    def link(self):
        if self.link_page:
            return self.link_page.url
        elif self.link_document:
            return self.link_document.url
        else:
            return self.link_external

    panels = [
        FieldPanel('link_external'),
        PageChooserPanel('link_page'),
        DocumentChooserPanel('link_document'),
    ]

    class Meta:
        abstract = True

person pjgb    schedule 13.05.2015    source источник


Ответы (2)


Вы должны иметь возможность определить @property в классе ParentPage. Что-то типа:

class ParentPage(Page):
    ...
    @property
    def related_pages(self):
        pages = ParentPageRelatedLink.objects.filter(page_id=self.id)
        return pages
person rnevius    schedule 14.05.2015
comment
Правильно, поэтому (лучший) способ сделать это — запросить все классы в ChildPage.parent_page_types и получить доступ к этому свойству для каждого из них. Поскольку у меня есть ParentPage1, ParentPage2, ParentPageN... я не могу знать, какие родительские страницы имеют текущую ChildPage в качестве связанной страницы. - person pjgb; 14.05.2015
comment
Вот как я это делал... но не уверен, что это лучший способ. - person rnevius; 14.05.2015
comment
Спасибо, это все, о чем я тоже мог думать. Это просто кажется ужасно неэффективным, так как будет запрос для каждой ParentPage. Но я могу цепляться за миллисекунды, которые на самом деле не имеют значения. Это просто кажется неуклюжим. - person pjgb; 14.05.2015
comment
И теперь я понимаю, что тоже смешал разные вещи... parent_page_types не имеет ничего общего со связанными страницами. Пора переосмыслить весь аппарат. - person pjgb; 14.05.2015
comment
Согласовано. В Трясогузке есть несколько подобных вещей (все вращаются вокруг отношений ParentalKey). Вы можете посетить Группу Google, чтобы получить более точный ответ (я получил хорошая информация непосредственно от основной команды). - person rnevius; 14.05.2015

Попробуй это:

parent_pages = ParentPage.objects.filter(related_links__linked_page=child_page)

«related_links» берется из атрибута related_name ParentalKey в модели, которую вы хотите запросить. «linked_page» — это поле в модели ParentPageRelatedLink, по которому вы хотите отфильтровать.

https://docs.djangoproject.com/en/1.8/topics/db/queries/#lookups-that-span-relationships

parent_page_types не имеет отношения к запрашиваемым страницам. Он используется для добавления ограничения на типы страниц, под которыми может быть создан определенный тип страницы (например, вы можете сказать, что запись в блоге может быть создана только в блоге). Это не связано с тем, как запрашиваются страницы

person Karl Hobley    schedule 15.05.2015
comment
К вашему сведению, Карл — один из основных разработчиков Трясогузки :) Как услужливо отмечает Рневиус, вы всегда можете задавать подобные вопросы в группе Google, которая находится под более тщательным контролем. Удачи! groups.google.com/forum/#!forum/wagtail - person tomd; 15.05.2015
comment
Спасибо, это похоже на то, что предложил @rnevius. Нет ли способа сделать что-то вроде ChildPage.all_pages_that_have_this_childpage_as_related_link? tomd Спасибо, я буду иметь в виду группу Google. - person pjgb; 15.05.2015
comment
Да, вы можете добавить приведенный выше запрос к модели ChildPage, как предложил Рневиус: - person Karl Hobley; 18.05.2015