【问题标题】:Django - Redirect page slug to detailview - shortening urlsDjango - 将页面 slug 重定向到详细视图 - 缩短 url
【发布时间】:2020-05-28 20:09:18
【问题描述】:

好的,我有一个简单的设置,其中包含属于某些类别的页面。

在我的网址中有

path('<slug:category_slug>/', views.PageByCategoryView.as_view(), name='page_by_category'),
path('<slug:category_slug>/<slug:page_slug>/', views.PageDetailView.as_view(), name='page_detail'),

例如;

www.mywebsite.com/activities/cycling/

指向有关骑行的页面的正确详细视图。

现在我想如果我们可以缩短网址就好了;

www.mywebsite.com/cycling/

于是我写了如下视图;

def redirect_with_category(request, page_slug):
    '''
    This redirect view points to the canonical url
    '''
    page = get_object_or_404(Page, slug=page_slug)
    return redirect(page, permanent=True)

urls.py是这样的;

path('<slug:category_slug>/', views.PageByCategoryView.as_view(), name='page_by_category'),
path('<slug:page_slug>/', views.redirect_with_category, name='page_detail_redirect'),
path('<slug:category_slug>/<slug:page_slug>/', views.PageDetailView.as_view(), name='page_detail'),

现在我们遇到了麻烦,即使重定向有效。如果找不到匹配项,Django 将停止尝试解决 category_slug。

为了让它工作,Django 应该尝试解析在 category_slug 中找不到匹配项的下一个路径。

根据文档,显然 Django 抛出了一个错误; "or if an exception is raised during any point in this process, Django invokes an appropriate error-handling view"

有没有办法解决这个问题?如果在第一个 url 中没有找到匹配的 slug,是否可以强制 Django 查找下一个匹配结果?

所以我想重定向;

www.mywebsite.com/cycling/ 至:www.mywebsite.com/activities/cycling/

【问题讨论】:

  • 当然,因为任何 slug 都会匹配 &lt;slug:category_slug&gt;,因此第二个 url 永远不会“触发”。
  • 我建议只使用单个path('&lt;slug:any_slug&gt;/',[...],然后在视图中您可以使用try: except 先查找类别,然后在未找到类别时查找页面。
  • 本,这将是一个有效的选择。尽管出于 SEO 的目的,我想将类别保留在 url 中。

标签: python django redirect


【解决方案1】:

发生这种情况的原因是因为path('&lt;slug:page_slug&gt;/, …) 永远不会“触发”,因为如果您创建完全 重叠路径,那么您发出的每个请求都会被path('&lt;slug:category_slug&gt;/, …)“捕获”,最后一个永远不会被触发。一般来说,最好让路径不重叠完全,因为这意味着对于重叠,某个路径是不可访问的,人们可能打算这样做可访问。

因此,您应该在PageByCategoryView 视图中进行匹配,如果这给出了“命中”,则执行redirect,例如,您可以通过覆盖dispatch 方法(或get如果您只想重定向 GET 请求)。

from django.http import Http404
from django.shortcuts import get_object_or_404, redirect

class PageByCategoryView(ListView):

    # …

    def dispatch(self, *args, **kwargs):
        try:
            return super().dispatch(*args, **kwargs)
        except Http404:
            page = get_object_or_404(Page, slug=self.kwargs['category_slug'])
            return redirect(page)

因此,我们首先旨在通过调用super().dispatch(*args, **kwargs) 方法来正确处理请求。如果返回 404,我们尝试找到 Page 与 slug 等于 category_slug 并重定向到那里。如果同样失败,将返回 404。

【讨论】:

  • 早上好!试过你的建议,只是想知道除了之后的“Http404”是否应该在那里?我目前正在使用它,除了:..(没有 Http404)。
  • @KevinD.:通常一揽子异常是一个严重的反模式:en.wikipedia.org/wiki/Error_hiding
猜你喜欢
  • 2013-02-11
  • 2018-03-26
  • 2014-05-31
  • 2022-01-22
  • 2021-07-04
  • 1970-01-01
  • 2020-10-30
  • 2014-08-06
  • 1970-01-01
相关资源
最近更新 更多