【问题标题】:DRF: Should you manually handle exception?DRF:你应该手动处理异常吗?
【发布时间】:2021-08-23 03:08:11
【问题描述】:

我是第一次使用 Django REST 框架开发 API。

我想知道下面哪种类型是推荐的编程实践。

在代码类型 1 中,如果未找到记录,则返回 None,这在主要检索方法中进行检查。如果在检索方法中收到 None ,我手动返回一个 404 状态的响应。如果遇到任何其他错误(包括异常),我会手动返回 500 响应。

在代码类型 2 中,如果没有找到记录,那么我提出 Http404。引发的 Http404 条件由序列化程序处理,并与消息一起发送正确的 404 响应。 我对代码类型 2 的主要关注是,如果生成任何其他异常,代码是否会崩溃(因为我们没有 try-except 块。

推荐的 API 开发设计模式是什么?

代码类型 1:

def get_object(self, ca_number):#get single customer
    try:
        return CustomerDetailModel.objects.get(ca_number=ca_number)
    except CustomerDetailModel.DoesNotExist:
        return None    

def retrieve(self, request, pk=None): 
    try:
        data =self.get_object(ca_number = pk)
        if data == None: #Check if None, if true send 404 error
            return Response(status=status.HTTP_404_NOT_FOUND)
        serializer = CustomerDetailSerializer(data)
        return Response(serializer.data,status=status.HTTP_200_OK)
    except :
        return Response(status=status.HTTP_500_INTERNAL_SERVER_ERROR)

代码类型 2:

def get_object(self, ca_number):#get single customer
    try:
        return CustomerDetailModel.objects.get(ca_number=ca_number)
    except CustomerDetailModel.DoesNotExist:
        raise Http404

def retrieve(self, request, pk=None): 
    data = self.get_object(ca_number = pk)
    serializer = CustomerDetailSerializer(data)
    return Response(serializer.data,status=status.HTTP_200_OK)

【问题讨论】:

    标签: django-rest-framework


    【解决方案1】:

    首先,无需手动返回 HTTP_500_INTERNAL_SERVER_ERROR,因为 Django 会为您处理任何未捕获的异常。

    其次,如果我们只在您的代码示例之间进行选择,我会选择第二个。

    但是 Django 和 DRF 很棒,所以对于通用视图(这是您的情况),它们可以为您完成大部分工作,因此无需重新发明轮子。您的代码可以简化为:

    # views.py
    class CustomerDetailView(RetrieveAPIView):
        serializer_class = CustomerDetailSerializer
        queryset = CustomerDetailModel.objects.all()
        lookup_field = "ca_number"
    
    # urls.py
    urlpatterns = [path("customer_detail/<ca_number>/", CustomerDetailView.as_view(), name="detail")]
    

    如果您使用的是ModelViewSet 而不是RetrieveAPIView,则视图类看起来几乎相同,但应更改urls.py 以使用路由器。

    【讨论】:

    • 在 HTTP_500_INTERNAL_SERVER_ERROR 的情况下,DRF 将整个错误网页发送到我想避免的客户端,而是发送自定义错误消息或一些标准错误消息。如何使用我的第二个代码示例来实现这一点。
    • 通常500 错误意味着“发生了严重错误”,因此永远不应返回。如果预计某些事情会失败并且您想返回错误消息,那么400 状态更合适。它可以显式返回,也可以使用raise rest_framework.exceptions.ValidationError(message) 返回。但是我在您的第一个代码示例中看不到任何可以引发异常的东西 - get_object()Serializer 处理他们自己的大部分异常。无论如何,如果确实如此 - 它应该在它提出的地方被修复/处理,而不是在retrieve
    • 我正在使用托管在云上的数据库实例(数据库即服务)。如何报告丢失的连接?我需要创建自定义错误消息还是 DRF 会处理它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-16
    • 2020-09-21
    • 1970-01-01
    • 2010-11-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多