没有 404 重定向的 Django DetailView

Django DetailView without 404 redirect

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

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 方法)不是正确的 way/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 异常它 returns None

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(),而是将您自己的代码提供给 return 一个合适的对象。空对象可能作为特殊实体存在于数据库中(最好通过数据迁移创建),或者它可能(如此处)即时创建并且永远不会保存。在任何一种情况下,它都会有一些模板可以轻松测试的显着特征。