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