I've started using Django REST Framework, and it is simply magic!
Here is a technique I've used to input lists of primitive types and serializers with many=True
from functools import partial
from rest_framework import viewsets
from rest_framework.response import Response
from rest_framework import status
from my_app.serializers import MyNestedModelSerializer
...
class MyNestedModelViewSet(viewsets.ViewSet):
serializer_class = MyNestedModelSerializer
def create(self, request):
serializer = self.serializer_class(data=request.data)
# get the submodel list serializer since it can't render/parse html
submodel_list_serializer = serializer.fields['submodels']
# make a partial function by setting the submodel list serializer
partial_get_value = partial(custom_get_value, submodel_list_serializer)
# monkey patch submodel_list_serializer.get_value() with partial function
submodel_list_serializer.get_value = partial_get_value
if serializer.is_valid():
simulate_data = serializer.save()
# do stuff ...
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
The function `custom_get_value()` uses JSON to parse the input:
def custom_get_value(serializer, dictionary):
if serializer.field_name not in dictionary:
if getattr(serializer.root, 'partial', False):
return empty
# We override the default field access in order to support
# lists in HTML forms.
if html.is_html_input(dictionary):
listval = dictionary.getlist(serializer.field_name)
if len(listval) == 1 and isinstance(listval[0], basestring):
# get only item in value list, strip leading/trailing whitespace
listval = listval[0].strip()
# add brackets if missing so that it's a JSON list
if not (listval.startswith('[') and listval.endswith(']')):
listval = '[' + listval + ']'
# try to deserialize JSON string
try:
listval = json.loads(listval)
except ValueError as err:
# return original string and log error
pass
# set the field with the new value list
dictionary.setlist(serializer.field_name, listval)
val = dictionary.getlist(serializer.field_name, [])
if len(val) > 0:
# Support QueryDict lists in HTML input.
return val
return html.parse_html_list(dictionary, prefix=serializer.field_name)
return dictionary.get(serializer.field_name, empty)