djangodjango-rest-frameworkdjango-viewsdjango-serializer

Using a serializer to validate data in a custom django REST API view


I am trying to build a custom API view and I stumbled over 2 problems, one more general, the other one more specific:

I have a custom view where I create a an object from the data sent in the api-request:


@api_view(["POST"])
def graph_create_view(request):
    """
    """

    network = Network.objects.get(name=request.data["network"])

    graph = Graph.objects.create(
        network_id=network.id,
        name=request.data["name"],
        description=request.data["description"],
        field2==request.data["field"],
        field3==request.data["field"],
        field4==request.data["field"],
        field5==request.data["field"],
        field6==request.data["field"],
        field7==request.data["field"],
    graph.save()

    return Response(HttpResponse.status_code)

That works well, when I send all the data specified in the Graph.objects.create method. When I do not send all the data but leave out a field (Let's say I send for example data without the description field) I get a key-error. That makes sense, because that key is actually missing. I could circumvent this with many if-else-statements but that is cumbersome, not practical and hard to maintain.

Now, I know I probably should write a generic view and not build this myself like this. The problem is that I need to create a Graph with two nested serializers attached to it and this is quite complicated to implement when overwriting the create method. Because the graph has two more models related to it for which I also create objects and then add it to the graph. Roughly, like this with two models:

        new_node = Node.objects.create(
            graph=graph,
            name=data_node["name"],
        )
        new_node.save()

My specific question: Is there a way of validating the data or use a serializer in this custom API-view so that the fields I don't send are filled with None-values?

My general question: Assuming I'd use a generic API-view, is it recommendable to overwrite the create-method when having two nested serializers or what would be the way to go?

Thanks so much in advance, very much appreciate the time, help and insights.


Solution

  • Yes, you can use DRF serializer to validate the data as well as you can fill with default values.

    Assume you have a serializer as follows,

    class FooSerializer(serializers.Serializer):
        foo = serializers.CharField(default='')
        bar = serializers.CharField(default=None)
        foo_bar = serializers.CharField()
    

    Here foo_bar field id required (by default), rest of the fields are required too, but in presence of default DRF will patch the default values.

    In [2]: s = FooSerializer(data={'foo_bar': 'This is foo_bar'})                                                                                                                                                     
    
    In [3]: s.is_valid()                                                                                                                                                                                               
    Out[3]: True
    
    In [4]: s.validated_data                                                                                                                                                                                           
    Out[4]: OrderedDict([('foo', ''), ('bar', None), ('foo_bar', 'This is foo_bar')])
    

    Here .validated_data is used in the create() method of Serializer class. You can see, foo and bar fields are filled with the default values we have provided in the serializer definition.


    Assuming I'd use a generic API-view, is it recommendable to overwrite the create-method when having two nested serializers or what would be the way to go?

    We have two create methods,

    1. create() method of viewsets.ModelViewSet
    2. create() method of serializer.Serializer (or its subclasses)

    Overriding the create() method of serializer is the DRF way to handle writable nested serializers.