我有一个结构类似的网站:
首页:动物
子页面:猫
子页面:狗
首页:猫
子页面:食物
首页:狗
子页面:食物
这样,用户可以转到站点/动物或站点/猫。动物是高级信息,猫和狗是站点的更详细部分。
我要做什么:
有时,我希望能够重用Animals中的页面并将其用于Cat或Dog中。但我不希望该网址从一个部分切换到另一部分。
示例:如果用户位于“动物”下,并且他们单击食品文章,则网址应为:
animals/cats/food_article
如果他们在cats下单击同一篇文章,则网址应如下所示:
cats/food_article
我尝试过的事情:
我尝试使用RoutableRouteMixin
。但这适用于子页面,不适用于同一级别的页面。
我尝试覆盖文章模型的get_url_parts
方法。但是随后出现404错误,因为页面实际上并不存在于我创建的url中。
这可以在Wa中实现吗?还是有可以与Wagtail一起使用的Django解决方案?
答案 0 :(得分: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中的服务功能以进行匹配。 但是,这可能取决于您的网站。
答案 1 :(得分:1)
get_children
方法,该方法位于每个Page
上,并且来自django-treebeard
。路由逻辑使用此方法来确定页面是否是另一个页面的子页面(读取URL时)。AnimalPage
,然后创建了ArticlePage
(例如,食品文章),然后进入狗页和猫页,并将食品文章链接到该页面。http://localhost:8000/food-article/
,http://localhost:8000/animals/cats/food-article/
和http://localhost:8000/animals/dogs/food-article/
。ArticlePage
置于其自己的父页面下,然后使用routablemixin使该页面不显示任何内容子网址。
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