问题
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