更改页面在 URL 中的显示位置

Change where a Page is displayed in the URL

我已经设置了我的网站,其中主要 parental/tree 结构是 Home > Shop > Category > Product",其中 > 表示 的父级。

这工作正常,但是当访问 Product(Page) 时,url 被 Wagtail 自动(并且正确地)配置在 /shop/test-category/test-product

我想更改它,以便产品实际显示为根级别(即使它不是)。因此,如果用户访问测试产品,它将位于 /test-product/.

查看文档,RoutablePageMixin 似乎可以解决问题,但我不知道如何实施它。有什么想法吗?

此解决方案将使产品在 URLS:

  • /shop/test-category/test-product/
  • /test-product/

方法:

您说得对,您将需要使用 RoutablePageMixin,请务必在导入前按照说明将其安装在您的 installed_apps 中。

下面的示例将 RoutablePageMixin 添加到您的 HomePage,因为这是将位于根 / URL 的页面。我们在尾随 /.

之前对单个 slug 进行正则表达式检查和匹配

然后我们看看是否可以找到带有该 slug 的 ProductPage,并提供(或重定向)到该页面。最后,如果没有匹配项,我们将使用当前请求调用 home_page 的 serve 方法来处理其他任何事情。这可能是不正确的 URL 或正确的子页面 URL.

注意事项:

  • 如果您在与产品页面相同的 slug 中有一个子页面,则该子页面将永远不会加载,此代码中没有智能可以解决这个问题。如果将来这成为问题,您可以在产品名称和子页面名称的验证中添加一些逻辑。
  • 这不考虑 SEO 问题,搜索引擎会将它们视为不同的页面,因此您可能需要考虑在元标记中声明您的 canonical URL
  • 这不会从 /shop/test-category/test-product/ 重定向回 /test-product/ - 这可以通过覆盖 ProductPage 上的 serve 方法并重定向到类似 home_page.url + '/' + self.slug.

示例代码:

# models.py - assuming all your models are in one file
from django.db import models
from django.shortcuts import redirect  # only needed if redirecting

from wagtail.admin.edit_handlers import FieldPanel
from wagtail.contrib.wagtailroutablepage.models import RoutablePageMixin, route
from wagtail.core.models import Page


class ProductPage(Page):
    price = models.DecimalField(max_digits=5, decimal_places=2)

    content_panels = Page.content_panels + [
        FieldPanel('price')
    ]


class HomePage(RoutablePageMixin, Page):

    @route(r'^(?P<product_slug>[\w-]+)/$')
    def default_view(self, request, product_slug=None):
        """Route will match any `my-product-slug/` after homepage route."""
        product_page = Page.objects.exact_type(ProductPage).filter(slug=product_slug).first()
        if product_page:
            # option 1 - redirect to the product's normal URL (non-permanent redirect)
            # return redirect(product_page.specific.url)
            # option 2 - render the product page at this URL (no redirect)
            return product_page.specific.serve(request)
        else:
            # process to normal handling of request so correct sub-pages work
            return self.serve(request)