【问题标题】:Django class-based view to return HttpResponse such as HttpResponseBadRequestDjango 基于类的视图返回 HttpResponse 如 HttpResponseBadRequest
【发布时间】:2021-04-26 08:30:09
【问题描述】:

我有一个继承自通用 DetailView 的自定义 Django 视图类。

通用DetailView 类依次调用其方法get_querysetget_object 和其他方法以生成一个对象以传递给Django 模板。

此外,通用DetailView 类在这些方法中引发Http404 异常以处理错误情况#

except queryset.model.DoesNotExist:
    raise Http404(_("No %(verbose_name)s found matching the query") %
                  {'verbose_name': queryset.model._meta.verbose_name})

我想做的很简单:如果在这些方法中发现错误,我想将其他 HTTP 状态代码返回给客户端。但是,因为Http404 是唯一一个有异常形式的Django HttpResponse,看来这不是很容易实现的。

因为HttpResponse 也不例外,所以我只好退回而不是提升它。因此,自定义的方法变成了如下形式。

def get_object(self, queryset=None):
   ...
   try:
      # Get the single item from the filtered queryset
      obj = queryset.get()
   except queryset.model.DoesNotExist:
      return HttpResponseBadRequest("Bad request.")

但是,上面的代码不会向客户端发送HttpResponseBadRequest。相反,它返回 HttpResponseBadRequest 作为 Django 模板的对象。客户端收到 200 状态代码,其中包含无效的模板对象。

唯一可能的解决方案是在 Django 模板中编写一些对象检查代码。但是,我想知道是否有更好的方法来处理这个问题。

【问题讨论】:

  • 你用的是什么版本的 Django?
  • 我使用的是最新版本,3.2。

标签: django


【解决方案1】:

从 Django 3.2 开始,我们现在有一个异常 BadRequest [Django docs],当它被捕获时,它会在内部变成 HttpResponseBadRequest,因此您可以尝试捕获 Http404 并引发 BadRequest

from django.core.exceptions import BadRequest


class MyView(SomeGenericView):
    ...
    
    def get_object(self, queryset=None):
        try:
            return super().get_object(queryset=queryset)
        except Http404 as e:
            # raise BadRequest("Bad request.") from e
            raise BadRequest("Bad request.")

对于某些以前的版本,我们可以尝试在 dispatch 方法处捕获异常并在那里返回适当的响应:

class MyView(SomeGenericView):
    ...
    
    def dispatch(self, request, *args, **kwargs):
        try:
            return super().dispatch(request, *args, **kwargs)
        except Http404:
            return HttpResponseBadRequest("Bad request.")

【讨论】:

  • 感谢您的回答。因为我还想使用其他一些 HTTP 状态码,所以我想我可以利用这两种方法。
  • @J.Choi 注意还有PermissionDenied 异常会变成403响应状态码
  • 只是给尝试做同样事情的其他人的注释:raise Exception("Message.") 将创建 500 响应,但是,handler500 不采用异常参数 [djangoticket]。因此,将raise Exception() 用于 500 代码和自定义消息似乎是不可能的。
猜你喜欢
  • 1970-01-01
  • 2011-03-06
  • 2017-03-28
  • 1970-01-01
  • 1970-01-01
  • 2014-07-10
  • 2015-06-26
  • 1970-01-01
相关资源
最近更新 更多