【问题标题】:Django DetailView without 404 redirect没有 404 重定向的 Django DetailView
【发布时间】:2020-06-22 12:32:01
【问题描述】:

我有一个带有 DetailView 类的小新闻应用程序,如下所示:

class DetailView(LoginRequiredMixin,generic.DetailView):
    model = NewsItem
    template_name = 'news/detail.html'

    def get_object(self):
        obj = super().get_object()

        if self.request.user.is_superuser or obj.published:
            return obj

和这样的 urls.py 配置:

urlpatterns = [
    path('', views.IndexView.as_view(), name='index'),
    path('<int:pk>/', views.DetailView.as_view(), name='detail'),
    path('<int:itemId>/publish', views.publish, name='publish'),
]

现在,当我将无效 ID 传递给详细视图时,它会自动重定向到 404。我想知道是否可以只将空对象传递给 DetailView。然后,模板将自行处理 404。

另外:尽管到目前为止它有效,但我觉得我处理权限要求的方式(覆盖 get_object 方法)不是正确的方式/Django 做事的方式

解决方案:我改变了 get_object 的覆盖,如下所示:

class DetailView(LoginRequiredMixin,generic.DetailView):
    model = NewsItem
    template_name = 'news/detail.html'

    def get_object(self):
        queryset = self.get_queryset()
        pk = self.kwargs.get(self.pk_url_kwarg)

        if pk is not None:
            queryset = queryset.filter(pk=pk)
        else:
            raise AttributeError("No article id provided")

        try:
            return queryset.get()
        except queryset.model.DoesNotExist:
            return None

它与原始的 get_object 方法基本相同,只是没有检查 slug 值,如果 queryset.get() 调用捕获 queryset.model.DoesNotExist 异常,它返回 None

【问题讨论】:

  • 编辑中的解决方案

标签: django django-views http-status-code-404


【解决方案1】:

Classy CBVs, 像往常一样,说明一切。

如果您不喜欢错误 id 的 404,则需要在更大程度上覆盖 get_object,因为它会引发错误 id 的异常 Http404。有问题的代码是

 try:
    # Get the single item from the filtered queryset
    obj = queryset.get()
 except queryset.model.DoesNotExist:
    raise Http404(_("No %(verbose_name)s found matching the query") %
                  {'verbose_name': queryset.model._meta.verbose_name})
 return obj

你可以在调用obj = super().get_object()时捕获异常

try:
    obj = super().get_object()
except Http404:
    obj = NewsItem( ... ) # a dummy empty NewsItem

或者你可以根本不调用 super() 并提供你自己的代码来返回一个合适的对象。空对象可能作为特殊实体存在于数据库中(最好由数据迁移创建),或者它可能(如这里)动态创建并且从不保存。在任何一种情况下,它都会具有模板可以轻松测试的一些显着特征。

【讨论】:

  • 非常感谢!我更改了 get_object 方法,并在 queryset.filter(pk=pk) 未找到对象时返回 None 我将相应地编辑我的问题
猜你喜欢
  • 2022-11-06
  • 2018-05-18
  • 2019-10-21
  • 1970-01-01
  • 2011-09-21
  • 2020-02-16
  • 1970-01-01
  • 1970-01-01
  • 2021-07-28
相关资源
最近更新 更多