单个内容,多个 URL?

Single piece of content, multiple URLs?

我有一个可以使用一些建议的用例。

我们发布了多个产品,每个产品在网站上都有自己的子树。通常,一段内容只会发布到一个产品,例如一篇新闻文章发布到产品 A,可以在 URL.

访问

但是,有时我们有想要发布到多个产品的内容,例如一篇新闻文章发布到产品 A、B 和 C,并将在 3 个不同的 URL 秒可用。

使用我们当前的 CMS,我们最终通过复制和粘贴内容来完成此操作,这对编辑来说很麻烦,尤其是当内容需要更新时。

理想的情况是,编辑者在一个地方编辑内容,指定要发布到的产品,内容由多个 URL 提供,并使用特定于产品的模板.

似乎 RoutablePageMixin 在这里很有用,但我不确定如何处理让编辑器指定目标产品并让路由知道该选择。

有人用 Wagtail 解决过类似的问题吗?

与其将您的新闻文章视为一种或多种产品的子对象,不如将它们视为按产品分类的一大堆新闻文章。然后,您的产品页面将有效地成为经过过滤的新闻文章索引页面。

以下是我的建模方式:

  • 如果您希望您的新闻文章以独立于任何特定类别的规范 URL 存在,或者您想要使用页面审核 and/or 预览,请将 NewsArticle 定义为页面模型;否则,将其定义为片段或 ModelAdmin 托管模型。
  • 在 NewsArticle 模型上,有一个 InlinePanel,编辑可以根据需要在其中关联尽可能多的相关产品:

    class NewsArticle(Page):
        body = RichTextField()
        date = models.DateField()
    
        content_panels = Page.content_panels + [
            FieldPanel('body'),
            FieldPanel('date'),
            InlinePanel('related_products', label="Related products"),
        ]
    
    class NewsArticleRelatedProduct(Orderable):
        news_article = ParentalKey(NewsArticle, related_name='related_products')
        product = models.ForeignKey(ProductPage, on_delete=models.CASCADE, related_name='news_articles')
    
        panels = [
            PageChooserPanel('product'),
        ]
    
  • 在您的 ProductPage 模型上,添加一个方法,该方法 returns 新闻项目的查询集,适当地过滤和排序:

    class ProductPage(Page):
        # ...
        def get_news_articles(self):
            return self.news_articles.live().order_by('-date')
    

然后,您可以使用 {% for news_article in page.get_news_articles %}.

之类的标签循环浏览产品页面模板中的新闻文章

我在Wagtail中解决了类似的问题,RoutablePageMixin是解决这个问题的关键。

如果你有 /blog/A/slug-product/, /blog/B/slug-product/, /blog/C/slug-product/ ,那么你可以在这里得到 slug 值 slug-product ,然后使用这个值来搜索数据库中的不同内容。

class BlogPage(RoutablePageMixin, Page):
    def get_posts(self):
        return PostPage.objects.descendant_of(self).live()
    @route(r'^(\d{4})/(\d{2})/(\d{2})/(.+)/$')
    def post_by_date_slug(self, request, year, month, day, slug, *args, **kwargs):
        post_page = self.get_posts().filter(slug=slug).first()
        return Page.serve(post_page, request, *args, **kwargs)

如您所见,我没有使用 url 的日期信息,而是使用 slug 值来获取博客 post 对象,您可以按照此处的模式使用正则表达式进行匹配你想要的url。

如果 urls 中的 slug 值也不同,此解决方案可能不会很好地工作,但在大多数情况下,此解决方案可以正常工作。

我写了一篇博客post讲如何使用RoutablePageMixin使页面可路由,如果你想了解更多关于RoutablePageMixin的信息,你可以查看这个link。

Routable Page