Трясогузка: Как фильтровать дочерние элементы индексной страницы, если доступ к индексной странице осуществляется через внешний ключ
Прошу прощения за возможные ошибки, английский не мой родной язык.
Я делаю сайт с новостями и событиями нескольких организаций (у каждой организации есть свой аккаунт, позволяющий им самостоятельно создавать новости и события).
На примере новостей:
NewsIndexPage
является родителем для всех NewsArticlePage
.
Каждый NewsArticlePage
связан с организацией.
По url /news/
NewsIndexPage
показывает все новости и позволяет фильтровать новости по организациям с помощью RoutablePageMixin
(/news/organization/<str: organization_slug>/
).
Также у каждой организации есть своя посадочная страница (OrganizationPage
) с информацией об организации и разделом новостей.
В разделе новостей отображается до 3 последних новостей организации (как в репозитории bakerydemo, когда последние 3 записи в блоге перечислены в HomePage
:
- https://github.com/wagtail/bakerydemo/blob/1d9247f0f516dd842da995b1d67fadcd7d644f7d/bakerydemo/base/models.py#L305
- https://github.com/wagtail/bakerydemo/blob/1d9247f0f516dd842da995b1d67fadcd7d644f7d/bakerydemo/templates/base/home_page.html#L30).
Каждый OrganizationPage
ссылается на NewsIndexPage
через ForeignKey
.
Но я не знаю, как отфильтровать дочерние элементы NewsIndexPage
, если доступ к ним осуществляется через ForeignKey
.
Когда я обращаюсь к экземпляру OrganizationPage
, я хочу передать slug организации в связанный NewsIndexPage
, чтобы я мог фильтровать дочерние NewsArticlesPage
s.
Единственное, что я придумал, это создать template_tag, который будет передавать slug в качестве аргумента какой-нибудь функции get_news_articles(self, organization_slug)
. Но мне пока не удалось этого сделать
news.models:
организации. Модели:
class Organization(index.Indexed, models.Model):
# ...
name = models.CharField(max_length=255)
# ...
slug = models.SlugField(
verbose_name=_("Slug Name"),
max_length=255,
unique=True,
blank=True,
null=False,
)
# ...
class OrganizationPage(Page):
"""
An organization page.
"""
organization = models.OneToOneField(
to=Organization,
on_delete=models.SET_NULL,
related_name="organization_page",
verbose_name=_("Organization"),
null=True,
blank=True,
)
# Featured sections on the HomePage
# News section
news_section_title = models.CharField(
blank=True, max_length=255, help_text=_("Title to display")
)
news_section = models.ForeignKey(
"news.NewsIndexPage",
null=True,
blank=True,
on_delete=models.SET_NULL,
related_name="+",
help_text=_(
"News section. Will display up to three latest news articles."
),
verbose_name=_("News section"),
)
content_panels = Page.content_panels + [
MultiFieldPanel(
[
FieldPanel("news_section_title"),
FieldPanel("news_section"),
],
heading=_("News section"),
),
]
private_panels = [
FieldPanel("organization"),
]
edit_handler = TabbedInterface([
ObjectList(content_panels, heading=_("Details")),
ObjectList(Page.promote_panels, heading=_("Promote")),
ObjectList(private_panels, heading=_("Admin only"), permission="superuser"),
])
# Specifies parent to OrganizationPage as being OrganizationsIndexPage
parent_page_types = ["OrganizationsIndexPage"]
# Specifies what content types can exist as children of OrganizationPage.
# subpage_types = ["news.NewsIndexPage"]
subpage_types = []
class Meta:
verbose_name = _("Organization page")
verbose_name_plural = _("Organization pages")
templates/organizations/organizations/organization_page.html:
<!-- ... -->
<div class="container">
<div class="row">
<div class="news-articles-list">
{% if page.news_section %}
<h2 class="featured-cards__title">{{ page.news_section_title }}</h2>
<div class="row">
{% for news_article in page.news_section.children|slice:"3" %}
{% include "includes/card/news-listing-card.html" with news_article=news_article %}
{% endfor %}
</div>
<a class="featured-cards__link" href="/news/organization/{{ page.slug }}">
<span>View more of our news</span>
</a>
{% endif %}
</div>
</div>
</div>
<!-- ... -->
Буду благодарен за любую помощь и советы!
Не пытайтесь фильтровать запрос внутри шаблона - сделайте это в get_context
методе на модели страницы:
class OrganizationPage(Page):
# ...
def get_context(self, request, *args, **kwargs):
context = super().get_context(request, *args, **kwargs)
context['news_articles'] = NewsArticlePage.objects.child_of(self.news_section).filter(organization=self.organization).live()[:3]
return context
Это сделает переменную news_articles
доступной в шаблоне, по которой вы можете выполнить цикл:
{% for news_article in news_articles %}
{% include "includes/card/news-listing-card.html" with news_article=news_article %}
{% endfor %}