如何向 ModelViewset 响应添加额外的字典?

How to add an extra dictionary to ModelViewset response?

使用模型

class Sim(modesl.Model):
    iccid = models.CharField(max_length=64)
    carrier = models.CharField(max_length=50)
    status = models.CharField(max_length=100)
    
    class Meta(object):
       app_label = "app"
       verbose_name = "Sim"
    class JSONAPIMeta:
       resource_name = "sim"
       external_field = "id"

使用视图 :

class SimView(viewsets.ModelViewSet):
    
    queryset = Sim.objects.all()
    serializer_class = SimSerializer

使用序列化程序:

class SimSerializer(serializers.ModelSerializer):

    class Meta:
        model = Sim
        fields = "__all__"

for /get/

{
    "links": {
        "first": "some link",
        "last": "some link"
        "next": null,
        "prev": null
    },
    "data": [
        {
            "type": "sim",
            "id": "1",
            "attributes": {
                "carrier": "Vodaphone",
                "iccid": "12345678912345678912",
                "status": "UnManaged",

            }
        }
    ],
    "meta": {
        "pagination": {
            "count": 1,
            "limit": 20,
            "offset": 0
        }
    }
}

现在我想在响应中发送字典“license_info”,它应该在响应中只出现一次,因此响应可能如下所示:

{
    "links": {
        "first": "some link",
        "last": "some link"
        "next": null,
        "prev": null
    },
    "data": [
        {
            "type": "sim",
            "id": "1",
            "attributes": {
                "carrier": "Vodaphone",
                "iccid": "12345678912345678912",
                "status": "UnManaged",

            }
        }
      #Either add here 
      {
       "license_info":"some value"   
      }
    ],
    "meta": {
        "pagination": {
            "count": 1,
            "limit": 20,
            "offset": 0
        }
    }
 #Or Add here 
  "license_info":{
     "some key value pairs"
  }

}

我试图将 license_info 设置为 属性,但每个实例都会重复此操作。

我尝试的另一种方法是覆盖 list 方法

def list(self, request, *args, **kwargs):

        instance = self.filter_queryset(self.get_queryset())
        page = self.paginate_queryset(instance)
        if page is not None:
            serializer = self.get_serializer(page, many=True)
        else:
            serializer = self.get_serializer(instance, many=True)

        serializer_data = serializer.data # get the default serialized data 
        serializer_data.append({"license_info": "some value"})
        return self.get_paginated_response(serializer.data) if page else Response(serializer_data)

但这给出了以下错误:

"/home/pranav/Desktop/cp_projects/connector/venv/lib/python3.7/site- 
packages/rest_framework_json_api/renderers.py\", line 589, in render\n    
resource_instance = serializer.instance[position]  # Get current instance\nIndexError: 
list index out of range", "status_code": 500, "request": "<WSGIRequest: GET 
'/api/v1/sim'>", "level": "ERROR"} 

我也试过了:

def list(self, request, *args, **kwargs):
    
            instance = self.filter_queryset(self.get_queryset())
            page = self.paginate_queryset(instance)
            if page is not None:
                serializer = self.get_serializer(page, many=True)
            else:
                serializer = self.get_serializer(instance, many=True)
    
            newdict = []
            newdict.append(serializer.data)
            newdict.append({"license_info": "some value"})
            return Response(newdict, status=status.HTTP_201_CREATED)

但是使用这个我得到了没有“链接”和“元”键值的响应负载。

我正在为 rest_framework 使用以下设置:

"DEFAULT_PAGINATION_CLASS": "rest_framework_json_api.pagination.JsonApiLimitOffsetPagination",
    "PAGE_SIZE": env["max_page_size"],
    "DEFAULT_PARSER_CLASSES": ("rest_framework_json_api.parsers.JSONParser",),
    "DEFAULT_RENDERER_CLASSES": rest_framework_json_api.renderers.JSONRenderer,
    "DEFAULT_METADATA_CLASS": "rest_framework_json_api.metadata.JSONAPIMetadata",

要以给定的方式向响应添加额外的字典,您可以创建自定义分页 class 并覆盖 get_paginated_response,这将 return 以所需的方式响应和然后在列表方法中,您可以动态更改该额外字典的值。

class CustomLimitOffsetPagination(JsonApiLimitOffsetPagination):
    
    def get_paginated_response(self, data):
        return Response(
            {
                "results": data,
                "meta": {
                    "pagination": OrderedDict(
                        [
                            ("count", self.count),
                            ("limit", self.limit),
                            ("offset", self.offset),
                        ]
                    )
                },
                "links": OrderedDict(
                    [
                        ("first", self.get_first_link()),
                        ("last", self.get_last_link()),
                        ("next", self.get_next_link()),
                        ("prev", self.get_previous_link()),
                    ]
                ),
              #Extra dictionary 
              "license_info":OrderedDict(),

            }
        )

在设置中为您添加此分页 class rest_framwork

"DEFAULT_PAGINATION_CLASS": "path to your CustomLimitOffsetPagination",

现在要向“license_info”添加值,您必须覆盖视图中的列表方法

def list(self,request,*args,**kwargs):
   instance = self.filter_queryset(self.get_queryset())
   page = self.paginate_queryset(instance)
   response = None
   
   if page is not None:
     serializer = self.get_serializer(page,many=True)
     response = self.get_paginated_response(serializer.data)
     response.data["license_info"] = OrderedDict(
                        [
                            ("key", "value"),
                        ]
                    )
   else:
     serializer = self.get_serializer(instance,many=True)
     response_data = []
     response_data.extend(serializer.data)
     response_data.append({"license_info":"some value"})
     response = Response(response_data)
   
   return response