Как добавить дополнительный словарь в ответ ModelViewset?

использование модели

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 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"} 

Я использую следующие настройки для 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",

Для добавления дополнительного словаря в ответ указанным способом вы можете создать пользовательский класс pagination и переопределить get_paginated_response, который будет возвращать ответ указанным способом, а затем в методе list вы можете динамически изменять значение этого дополнительного словаря.

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(),

            }
        )

Добавьте этот класс paginate для вас rest_framwork в настройках

"DEFAULT_PAGINATION_CLASS": "path to your CustomLimitOffsetPagination",

Теперь для добавления значения в "license_info" необходимо переопределить метод list в представлениях

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
Вернуться на верх