【问题标题】:DRF: Which if better to create custom structure of response in Serializer/ModelSerializer?DRF:在 Serializer/ModelSerializer 中创建自定义响应结构哪个更好?
【发布时间】:2023-01-20 20:15:02
【问题描述】:

我目前正在Django Rest Framework 上制作一个简单的CRUD 应用程序。

对于特定结构中的任何请求,我需要向客户端返回响应。

例如,如果客户端发出POST请求创建一条新记录并成功执行,则API需要返回这样的结构:

{
    "data": [
        {
            "id": 1,
            "email": "bobmarley@gmail.com",
        }
    ],
    "error": {}
}

假设问题与模型字段有关。在这种情况下,API 应该返回这样的结构:

{
    "data": [],
    "error": {
        "email": [
            "This field is required."
        ]
    }
}

如果问题与模型字段无关,则有必要向客户端返回这样的结构,其中会有错误的描述:

{
    "data": [],
    "error": {
        "non_field_errors": [
            "Description of the error."
        ]
    }
}

根据错误,我还必须在查询响应中返回不同的状态。

openapi-schema.js:

  /clients:
    post:
      summary: Create New Client
      operationId: post-clients
      responses:
        '200':
          description: Client Created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Result'
              examples: {}
        '400':
          description: Missing Required Information
        '409':
          description: Email Already Taken

我当前的代码返回不正确的结构。我应该在序列化级别配置所有这些吗?

{
    "data": [],
    "error": {
        "non_field_errors": [
            "{'email': [ErrorDetail(string='person with this email already exists.', code='unique')]}"
        ]
    }
}

模型.py:

class Client(models.Model):
    id = models.AutoField(primary_key=True)
    email = models.EmailField(unique=True)

    class Meta:
        db_table = "clients"

def __str__(self):
    return self.email

序列化程序.py:

class ClientSerializer(serializers.ModelSerializer):
    class Meta:
        model = Client

意见.py:

class ClientView(APIView):
    def post(self, request):
        data = []
        error = {}
        result = {"data": data, "error": error}
        try:
            client_serializer = ClientSerializer(data=request.data)
            client_serializer.is_valid(raise_exception=True)
            client_serializer.save()
            data.append(client_serializer.data)
            return Response(result, status=status.HTTP_201_CREATED)
        except Exception as err:
            error['non_field_errors'] = [str(err)]
            return Response(result, status=status.HTTP_200_OK)

【问题讨论】:

    标签: python django django-rest-framework django-views django-serializer


    【解决方案1】:

    这取决于你的身边

    {
        "data": [],
        "error": {
            "email": [
                "This field is required."
            ]
        }
    }
    

    我不得不说这有时是错误的,因为错误可能不同,我的意思是,可能有字符串验证、基于国家/地区的检查或其他。

    我建议这段代码

    {
        "data": [],
        "error": {
            "non_field_errors": [
                {'email': [ErrorDetail(string='person with this email already exists.', code='unique')]}
            ]
        }
    }
    

    在另一种情况下,您可能会遇到错误并手动将它们发送到客户端,例如:

    client_serializer = ClientSerializer(data=request.data) 
    if client_serializer.is_valid(): 
        return client_serializer.save() 
    else: 
        return {"errors": client_serializer.errors} 
    

    【讨论】:

    • 例如,如果在 POST 请求中省略了 Request Body 中的某些字段,则应返回第一个选项。我当前的代码返回第二个选项,这在我的例子中是不正确的。您对我需要更改的内容有什么想法吗?
    • 您是否尝试过序列化程序错误:
    • client_serializer = ClientSerializer(data=request.data) if client_serializer.is_valid(raise_exception=True): return client_serializer.save() else: return {"errors": client_serializer.errors}
    【解决方案2】:

    您可以根据需要返回响应数据。

    class ClientView(APIView):
        def post(self, request):
            data = []
            error = {}
            result = {"data": data, "error": error}
    
            try:
                client_serializer = ClientSerializer(data=request.data)
    
                if not client_serializer.is_valid():
                    result["error"] = client_serializer.errors
                    return Response(result, status=status.HTTP_400_BAD_REQUEST)
    
                client_serializer.save()
                data.append(client_serializer.data)
                result["data"] = data
                return Response(result, status=status.HTTP_201_CREATED)
    
            except Exception as err:
                result["data"] = []
                result["error"] = "Something went wrong"
                return Response(result, status=status.HTTP_200_OK)
    

    【讨论】:

      猜你喜欢
      • 2015-11-12
      • 2019-01-01
      • 1970-01-01
      • 2015-12-22
      • 2021-10-28
      • 2015-03-22
      • 2022-01-15
      • 2022-08-07
      • 1970-01-01
      相关资源
      最近更新 更多