鹡鸰:获取上一个或下一个兄弟姐妹

Wagtail: Get previous or next sibling

我正在用 wagtail 创建一个页面,我需要知道当前页面的上一个和下一个同级:

在我的肖像页面模型中,我试图定义两种方法来找到正确的 url,但我遗漏了一个关键部分。要获得第一个兄弟姐妹,我可以执行以下操作:

class PortraitPage(Page):

    ...

    def first_portrait(self):
        return self.get_siblings().live().first().url

first()last()方法,但似乎没有next()previous()方法来获取直接邻居(在令它们在 wagtail admin 中排列。

有什么办法可以实现吗?

调试了一段时间后,我发现wagtail已经有两个方法:get_prev_sibling()get_next_sibling()

所以这些方法可能看起来像这样(占前一个方法的第一页和下一个方法的最后一项):

def prev_portrait(self):
    if self.get_prev_sibling():
        return self.get_prev_sibling().url
    else:
        return self.get_siblings().last().url

def next_portrait(self):
    if self.get_next_sibling():
        return self.get_next_sibling().url
    else:
        return self.get_siblings().first().url

Django-Treebeard 提供 get_next_siblingget_prev_sibling,它们将 return 您在树中的直接兄弟姐妹,但这些不一定是您的下一个 发布兄妹。要请求那些你可以使用:

prev = page.get_prev_siblings().live().first()
next = page.get_next_siblings().live().first()

这显然也可以与任何其他查询集操作链接。

这是处理 non-published 兄弟姐妹的版本。

def next_portrait(self):
    next_sibling = self.get_next_sibling()
    if next_sibling and next_sibling.live:
        return next_sibling.url
    else:
        next_published_siblings = self.get_next_siblings(
            inclusive=False
        ).live()
        if len(next_published_siblings):
            return next_published_siblings[0].url
        return self.get_siblings().live().first().url

def prev_portrait(self):
    previous_sibling = self.get_prev_sibling()
    if previous_sibling and previous_sibling.live:
        return previous_sibling.url
    else:
        previous_published_siblings = self.get_prev_siblings(
            inclusive=False
        ).live()
        if len(previous_published_siblings):
            return previous_published_siblings[0].url
        return self.get_siblings().live().last().url

您可以在 class 中定义继承自 Page

的属性

兄弟姐妹

如果你想要 Page 实例的兄弟姐妹,你可以使用以下内容(基于 Danielle Madeley 的回答):

class PortraitPage(Page):
    # ...
    @property
    def next_sibling(self):
        return self.get_next_siblings().live().first()

    @property
    def prev_sibling(self):
        return self.get_prev_siblings().live().first()

相同的兄弟姐妹 class

如果你想要PortraitPage的兄弟姐妹,在type方法中指定self.__class__如下:

class PortraitPage(Page):
    # ...
    @property
    def next_sibling(self):
        return self.get_next_siblings().type(self.__class__).live().first()

    @property
    def prev_sibling(self):
        return self.get_prev_siblings().type(self.__class__).live().first()

模板

如果要在模板中使用它们,在定义属性后,执行以下操作:

{# This is a template #}
Previous Sibling: {{ page.next_sibling }}
Next Sibling: {{ page.prev_sibling }}

self.get_siblings() 如果您想根据仅在子 class 中找到的属性进行任何过滤,则会失败,因为 PageQuerySet 结果的类型为 Page.

对我来说,我有一个可以按类别或标签过滤的博客索引页面。 沼泽详细信息页面末尾有下一个和上一个博客 post 的卡片。 我希望那些 prev/next post 符合我登陆该页面的过滤器。

为了解决这个问题,您需要查询属于子 class 的对象(例如 BlogDetailPage),过滤这些对象,然后使用 [=20] 获取 prev/next post =]class.objects.sibling_of(自己):

def get_context(self, request, *args, **kwargs):
    context = super().get_context(request, *args, **kwargs)
    siblings = self.__class__.objects.sibling_of(self).live()
    category_filter = request.GET.get("category", None)
    tag_filter = request.GET.get("tag", None)
    if category_filter:
        siblings = siblings.filter(categories__slug__in=category_filter.split(","))
        context["filter"] = '?category=' + category_filter
    elif tag_filter:
        siblings = siblings.filter(tags__slug__in=tag_filter.split(','))
        context["filter"] = '?tag=' + tag_filter
    else:
        context["filter"] = ''
    context["next_post"] = siblings.filter(path__gt=self.path).first()
    context["previous_post"] = siblings.filter(path__lt=self.path).first()

    return context

我使用了 self.__class__.objects.sibling_of(self),因为这是一个超级 class 和子 classed 博客页面。