【问题标题】:Wagtail: Get previous or next siblingWagtail:获取上一个或下一个兄弟姐妹
【发布时间】:2015-05-20 09:13:11
【问题描述】:

我正在创建一个带有 wagtail 的页面,我需要知道当前页面的上一个和下一个兄弟:

在我的纵向页面模型中,我尝试定义两种方法来查找正确的 url,但我错过了一个关键部分。要获得第一个兄弟姐妹,我可以执行以下操作:

class PortraitPage(Page):

    ...

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

first()last() 方法,但似乎没有 next()previous() 方法来获取直接邻居(按照它们在 wagtail 管理员中的排列顺序) .

有什么办法可以做到吗?

【问题讨论】:

    标签: python django wagtail


    【解决方案1】:

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

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

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

    【讨论】:

    • 有什么方法可以在 Django 模板中实现相同的结果?
    【解决方案2】:

    调试了一会,发现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
    

    【讨论】:

    • 我想它来自页面模型,但我没有研究它。我刚刚做了一个dir(self) 并查看了可用的方法。它有效。你有哪个版本的鹡鸰?我正在开发 v.1.0b1
    • @rnevius 啊,来了,只在 wagtail 0.4 的发行说明中提到:docs.wagtail.io/en/latest/releases/0.4.html
    • 嗨 @nils 和 @rnevius,get_prev_sibling()get_next_sibling() 方法来自 Treebeard,它处理 Wagtail 的页面层次结构,并在此处记录:tabo.pe/projects/django-treebeard/docs/1.61/… @nils,如果您使用的是 1.0b1,您应该查看我们今天发布的 1.0b2:github.com/torchbox/wagtail/releases/tag/v1.0b2
    • 感谢@tomd 的信息!我们说话的时候我正在运行 beta2 ;-)
    • @tomd 我刚刚意识到“get_next_sibling()”不包含我在页面模型中定义的字段(例如“header_image”)。有没有办法访问这些?
    【解决方案3】:

    这是处理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
    

    【讨论】:

      【解决方案4】:

      你可以在你的类中定义继承自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()
      

      同级的兄弟姐妹

      如果您想要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 }}
      

      【讨论】:

        【解决方案5】:

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

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

        要解决这个问题,您需要查询属于子类的对象(例如 BlogDetailPage),过滤这些对象,然后使用 class.objects.sibling_of(self) 获取上一篇/下一篇文章:

        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),因为这是一个带有子类博客页面的超类。

        【讨论】:

          猜你喜欢
          • 2020-05-27
          • 2012-07-23
          • 2014-07-12
          • 1970-01-01
          • 2013-02-24
          • 1970-01-01
          • 1970-01-01
          • 2021-10-08
          • 1970-01-01
          相关资源
          最近更新 更多