如何在 DRF 中 return 自定义 JSON 响应?

How to return custom JSON response in DRF?

我已经为新闻模型创建了 API:

models.py

class News(models.Model):
    title = models.CharField(max_length=255)
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.title

serializers.py

class NewsSerializer(serializers.ModelSerializer):
    class Meta:
        model = News
        fields = [
            "id",
            "title",
            "created_at",
        ]

views.py

class NewsViewSet(ModelViewSet):
    serializer_class = NewsSerializer
    queryset = News.objects.all()

这个API的当前结果如下:

[
    {
        "id": 1,
        "title": "testing1",
        "created_at": "2022-04-02T16:05:08.353708Z",
    }
]

我的问题是有什么方法可以像下面这样更改响应格式吗?我不知道如何用 Django DRF 制作。

{
  "status": 0,
  "message": "Success",
  "data": {
    "updatedAt": "2020-08-31 17:49:15",
    "serverTime": "2022-03-23 15:10:11",
    "news": [
      {
        "id": 1,
        "title": "testing1",
        "created_at": "2022-04-02T16:05:08.353708Z",
      }
    ]
  }
}

您可以将 ModelViewSet 中的 list 方法覆盖为 return 自定义 response

class NewsViewSet(ModelViewSet):
    serializer_class = NewsSerializer
    queryset = News.objects.all()

    def list(self, request, *args, **kwargs):
        # call the original 'list' to get the original response.
        response_data = super(NewsViewSet, self).list(request, *args, **kwargs)

        data = {
              "status": 0,
              "message": "Success",
              "data": {
                      "updatedAt": "2020-08-31 17:49:15",
                      "serverTime": "2022-03-23 15:10:11",
              "news": [{
                        "id": obj['id'],
                        "title": obj['title'],
                        "created_at": obj['created_at'],
                          } for obj in response_data.data]
                      }
            }

        return Response(data)

考虑另一种方式:

class ResponseOptsMixin:

    def finalize_response(self, request, response, *args, **kwargs):
        response = super().finalize_response(request, response, *args, **kwargs)
        
        result_data = {
            "status": 0,
            "message": "Success",
            "data": {
                "updatedAt": "2020-08-31 17:49:15",
                "serverTime": "2022-03-23 15:10:11",
            },
        }
        model_name = self.queryset.model._meta.model_name
        result_data["data"][model_name] = response.data
        response.data = result_data

        return response


class NewsViewSet(ResponseOptsMixin, ModelViewSet):
    ...

在任何需要的地方使用这个 mixin