Django DRF ListField to deserialize list of ids in GET's queryparams

余生颓废 提交于 2019-12-11 13:43:37

问题


Tried to use DRF's ListField option to de-serialize list of values (applications in the example below) in query params. I'm having trouble making it work. Couldn't find with examples in the web. Hoping someone to throw some help.

api: /getAppStats/?applications=one,two,three

class MySerializer(serializers.Serializer):
 applications = serializers.ListField(child=serializers.CharField())
 start_date = serializers.DateField(default=(datetime.datetime.utcnow() - datetime.timedelta(days=30)).date().isoformat())
 end_date = serializers.DateField(default=datetime.datetime.utcnow().date().isoformat())

class SomeView(generics.GenericAPIView):
 """

 """
 permission_classes = [AllowAny]
 serializer_class = MySerializer

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

    """ 
    Just return query params..
    """
    serializer = MySerializer(data=request.query_params)

    if not serializer.is_valid():
        return Response({'stats':'invalid input data'})

    return Response({'stats':serializer.data})

All I see is this -

 {
            "stats": {
                "applications": [],
                "start_date": "2015-05-27",
                "end_date": "2015-06-26"
            }
        }

Am I sending the input params in incorrect way? Did I miss something trivial?

Thanks!


回答1:


The standard approach to send multiple parameters for same key is is to use the same key name twice.

You can do this:

/getAppStats/?applications=one&applications=two&applications=three

Also, your server will receive the applications as an array i.e. as applications[] and not applications.

class SomeView(generics.GenericAPIView):
 """

 """
 permission_classes = [AllowAny]
 serializer_class = MySerializer

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

    """ 
    Just return query params..
    """

    # get the applications list
    applications = request.query_params.getlist('applications[]')

    # create a dictionary and pass it to serializer
    my_data = {'applications': applications, ...}

    serializer = MySerializer(data=my_data)

    if not serializer.is_valid():
        return Response({'stats':'invalid input data'})

    return Response({'stats':serializer.data})



回答2:


This has been answered but I was also looking for a solution that did not involve reforming the serializer data by getting the values out of the request with getlist (otherwise what's the point).

If you use the ListField (and probably also if you use many=True) there is code in there that will handle the list, the problem is that it looks like you are using jQuery on the client which seems to cause the "ids[]" syntax which fouls up the serializers.

Here was the solution I would up using.




回答3:


But I wanted to avoid code to pull these values from query params manually and pass it again to serializer. I was expecting the serializer do that for me. – Satish

I also want the serializer to do this for me, but I haven't found it. And besides, I use this list of query_params for django-filter: MultipleChoiceFilter and ModelMultipleChoiceFilter, so DRF ListField will not work for me.

In my project, the Android request without [], but only IOS request with [].

My solution is to add a decorator to add data in request.query_params and request.data.

def update_get_list_params(func):
    def wraps(self, request, *args, **kwargs):
        request.query_params._mutable = True
        request.data._mutable = True
        for key in list(request.query_params.keys()):
            # Make sure you know this will not influence the other query_params
            if key.endswith('[]'):
                new_key = key.split('[]')[0]
                value = request.query_params.getlist(key)
                if value:
                    request.query_params.setlist(new_key, value)
        for key in list(request.data.keys()):
            if key.endswith('[]'):
                new_key = key.split('[]')[0]
                value = request.data.getlist(key)
                if value:
                    request.data.setlist(new_key, value)
        return func(self, request, *args, **kwargs)
    return wraps


@update_get_list_params
def get(self, request, *args, **kwargs):
     pass


来源:https://stackoverflow.com/questions/31083467/django-drf-listfield-to-deserialize-list-of-ids-in-gets-queryparams

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!