0

我有一个结构如下的网站:

首页:动物
子页面:猫
子页面:狗

首页:猫
子页面:食物

首页:
狗子页面:食物

这样,用户可以访问站点/动物或站点/猫。动物是高级信息,猫和狗是网站的更详细的部分。

我想做的事:
偶尔,我希望能够重用 Animals 的页面并在 Cat 或 Dog 中使用它们。但我不希望 url 从一个部分切换到另一个部分。

示例:如果用户在 Animal 下,并且他们点击食物文章,则 url 应该是: animals/cats/food_article

如果他们点击猫下的同一篇文章,则 URL 应如下所示: cats/food_article

我尝试过的:
我尝试过使用RoutableRouteMixin. 但这适用于子页面,不适用于同一级别的页面。

我尝试覆盖get_url_parts文章模型的方法。但是后来我收到了 404 错误,因为这些页面实际上并不存在于我创建的 url 中。

这可以在 Wagtail 中实现吗?或者是否有我可以与 Wagtail 一起使用的 Django 解决方案?

4

2 回答 2

1

潜在方法

  • 如果没有重大定制,您将需要为您的文章添加单独的页面模型,这些可以添加到根页面下,然后默认不显示(包括从您拥有的任何菜单设置中隐藏)。
  • 然后创建一个模型集群,它将成为您的动物页面(猫、狗)和文章页面之间的关系。
  • 最后,覆盖 Animal 页面的get_children方法,该方法位于 eachPage并且来自django-treebeard. 路由逻辑使用此方法来确定页面是否是另一个页面的子页面(读取 URL 时)。
  • 一旦你创建了几个AnimalPages,然后创建一个ArticlePage(例如食物文章),然后进入狗页面和猫页面并将食物文章链接到页面。
  • 此时,您将能够通过 3 个 URL 访问食品文章;http://localhost:8000/food-article/,http://localhost:8000/animals/cats/food-article/http://localhost:8000/animals/dogs/food-article/.
  • 您可以通过几种不同的方式使原始的 food-article URL 不起作用,但最简单的方法是将所有ArticlePages 放在它们自己的父页面下,然后使用 Routeablemixin 使该页面不显示任何子 URL。
    • 注意:如果您将所有文章放在它们自己的子页面下(例如ArticlesPage,这应该仍然有效,因为它只检查 URL 的“最后”部分)。我还没有测试过这个。

示例代码

from django.db import models

from modelcluster.fields import ParentalKey
from modelcluster.models import ClusterableModel

from wagtail.admin.edit_handlers import (
    InlinePanel,
    PageChooserPanel,
)

from wagtail.core.models import Orderable, Page

class ArticlePage(Page):
    # Articles will be available to link to any other AnimalPage and content shared

    content_panels = Page.content_panels

    subpage_types = [] # no sub-pages allowed

class RelatedArticle(models.Model):
    # http://docs.wagtail.io/en/v2.7.1/reference/pages/panels.html#inline-panels
    article_page = models.ForeignKey(
        'wagtailcore.Page',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+',
    )

    panels = [
        PageChooserPanel('article_page', 'base.ArticlePage')
    ]

    class Meta:
        abstract = True

class ArticlePageRelatedPages(Orderable, RelatedArticle):
    page = ParentalKey(
        'base.AnimalPage',
        on_delete=models.CASCADE,
        related_name='related_articles'
    )

class AnimalsPage(Page):
    # This is our root animals page

    content_panels = Page.content_panels

    subpage_types = ['AnimalPage']


class AnimalPage(Page):

    def get_articles(self):
        # returns a queryset (not a list) of all Pages that are linked articles
        return Page.objects.filter(id__in=[
            r.article_page.pk for r in self.related_articles.all()
        ])

    def get_children(self):
        # override the method from django-treebeard
        # can be used in the template or wherever needed for 'children'
        # this method is also used when attempting to find child urls
        sub_pages = super().get_children()
        articles = self.get_articles()
        return articles | sub_pages # merges the two querysets for the 'or' operator

    content_panels = Page.content_panels + [
        InlinePanel('related_articles', label='Related Articles'),
    ]

    subpage_types = [] # no sub-pages allowed
于 2020-01-12T06:11:13.657 回答
1

您可以如下创建 IncludePage 并使用它在不同的 url 下呈现相同的内容。

from django.db import models
from wagtail.core.models import Page
from wagtail.admin.edit_handlers import PageChooserPanel
from django.http import Http404


class IncludePage(Page):
    page  = models.ForeignKey('wagtailcore.Page',
                              null=True, blank=True,
                              on_delete=models.SET_NULL,
                              related_name='+')

    content_panels = Page.content_panels + [
              PageChooserPanel('page'),
             ]

    def get_template(self, *args, **kwargs):
        page = self.page.specific
        if type(page) == IncludePage:
            raise Http404("Avoid recursion")
        return page.get_template(*args, **kwargs)

    def get_context(self, *args, **kwargs):
        page = self.page.specific
        if type(page) == IncludePage:
            raise Http404("Avoid recursion")
        return page.get_context(*args, **kwargs)

但是请注意,这不适用于具有自定义服务功能的页面(例如,使用 RoutableRouteMixin 的页面)。对于那些您必须在 IncludePage 中复制服务功能以进行匹配的人。但根据您的网站,这可能会有用。

于 2020-01-12T05:09:43.910 回答