【问题标题】:Wagtail Custom URL based on slugs using RoutablePageMixin使用 RoutablePageMixin 基于 slugs 的 Wagtail 自定义 URL
【发布时间】:2019-01-14 16:30:20
【问题描述】:

我想更改博客条目的 URL 以包含类别的 slug (@route(r'^([category-slug]/[post-slug] - 例如 localost/health/health_blog_1)。

我将如何为此更改模型?

class PostPage(RoutablePageMixin, Page):
    body = RichTextField(blank=True)
    date = models.DateTimeField(verbose_name="Post date", default=datetime.datetime.today)
    categories = ParentalManyToManyField('blog.BlogCategory', blank=True)
    tags = ClusterTaggableManager(through='blog.BlogPageTag', blank=True)

    content_panels = Page.content_panels + [
        FieldPanel('body', classname="full"),
        FieldPanel('categories', widget=forms.CheckboxSelectMultiple),
        FieldPanel('tags'),
    ]

    settings_panels = Page.settings_panels + [
        FieldPanel('date'),
    ]

    @property
    def blog_page(self):
        return self.get_parent().specific

    def get_context(self, request, *args, **kwargs):
        context = super(PostPage, self).get_context(request, *args, **kwargs)
        context['blog_page'] = self.blog_page
        return context

【问题讨论】:

    标签: django wagtail


    【解决方案1】:

    暂时将RoutablePageMixin 放在一边,Wagtail 要理解的一点是,您不应该像对待常规 Django 网站(或 Rails 或任何将路由映射到视图/控制器的框架)那样考虑 URL )。使用 Wagtail,页面的路径是从页面树构建的。因此,如果您希望类别出现在路径中,它需要是树的一部分。在你的情况下,它会是这样的:

    HomePage (title: My Website, path: /)
    |- CategoryPage (title: Health, path: /health/)
    |  |- PostPage (title: Post 1, path: /health/post-1/)
    |  |- PostPage (title: Post 2, path: /health/post-2/)
    |  \- PostPage (title: Post 3, path: /health/post-3/)
    \- CategoryPage (title: Diet, path: /diet/)
    |- ...
    \- ...
    

    在这种情况下,您不需要任何进一步的修改。这很简单,您可以免费获得类别页面,其中可以列出该类别中的所有帖子。显然,这种解决方案的缺点是,这样一个帖子只能属于一个类别。

    现在让我们看看RoutablePageMixins 是如何工作的以及他们可以提供什么。它们允许您创建虚拟页面(树中不存在的页面)。他们通过为路径添加后缀来实现这一点,例如您在/blog/ 有一个BlogIndexPage,但您还希望在/blog/archives/<the-year>/ 提供年度档案,并在/blog/tags/<the-tag> 提供标签过滤。你能想到的方式(免责声明:它实际上不是这样工作的)是当 Wagtail 收到对 /blog/archives/<the-year>/ 的请求时,这条路径将不会存在于树中(/blog/archives/ 也不存在),但 /blog/确实如此,所以 Wagtail 会加载您的可路由页面并检查与 /archives/<the-year> 匹配的路由(因为它已经解析了 /blog/)。

    因此,如果您想修改当前页面路径之前的内容,RoutablePageMixin 必须是树中父页面声明的一部分。假设您的 PostPagees 是您的 HomePage 的直接子项,如下所示:

    HomePage (title: My Website, path: /)
    |- PostPage (title: Post 1, path: /health/post-1/)
    |- PostPage (title: Post 2, path: /health/post-2/)
    \- PostPage (title: Post 3, path: /health/post-3/)
    

    那么你会在HomePage的声明中包含RoutablePageMixin

    form django.shortcuts import get_object_or_404
    from wagtail.contrib.routable_page.models import RoutablePageMixin, route
    from wagtail.core.models import Page
    
    class HomePage(RoutablePageMixin, Page):
        # Some fields
    
        @route(r'^(?P<category_slug>[\w-]+)/(?P<page_slug>[\w-]+)')
        def post_page(self, requets, category_slug, page_slug):
            post = get_object_or_404(PostPage, slug=page_slug, category_slug=category_slug)
            context = {
                'post': post
            }
            return render(request, 'posts/post_page.html', context)
    

    但是现在您遇到了一个问题,因为您的帖子在技术上存在于 2 个不同的 URL,即 /&lt;category_slug&gt;/&lt;page_slug&gt;/(因为 RoutablePageMixin)和 /&lt;page_slug&gt;/(因为它在树中的位置)。您可以接受它,只需设置 canonical URL 或将您的帖子重定向到正确的 URL:

    form django.shortcuts import redirect
    from wagtail.core.models import Page
    
    class PostPage(Page):
        # Some fields
    
        def serve(self, request, *args, **kwargs):
            homepage = self.get_parent().specific
            url = homepage.url + homepage.reverse_subpage('post_page', category_slug=self.category_slug, page_slug=self.page_slug)
            return redirect(url)
    

    话虽如此,我建议不要使用redirect。这确实使 Wagtail 违背了它的核心原则。

    如果您确实更改了 URL 结构,使其与 Wagtail 的树路径不匹配,您还需要考虑更改站点地图 URL。

    class PostPage(Page):
    
        def serve(..):
            ....
    
        def get_sitemap_urls(self, request):
            """Overwrite the url."""
            return [
                {
                    "location": '',  # Reverse subpage url
                    "lastmod": (self.last_published_at or self.latest_revision_created_at),
                }
            ]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-08
      • 2022-01-02
      • 1970-01-01
      • 2013-07-24
      • 1970-01-01
      相关资源
      最近更新 更多