Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Serializing inside method field in Django REST framework

For example, I have two models: Model1 and Model2. They are not related directly to each-other by any key-field on a model level. For both models I have serializers. I am searching the way to have Model2 queryset in Model1 serializer. For example:

GET /api/model1/01

According to Model1 ID in request I can make query for Model2 objects that I need to be sent in response. For now I have solution that I don't like: in Model1 serializer I have method field that returns a list of objects. Is there any way to use Model2 serializer in method field of Serializer1 or any other solution for my case?

like image 878
napilnik Avatar asked Jun 09 '16 14:06

napilnik


People also ask

What is serializing in django?

Django's serialization framework provides a mechanism for “translating” Django models into other formats. Usually these other formats will be text-based and used for sending Django data over a wire, but it's possible for a serializer to handle any format (text-based or not).

What is the difference between ModelSerializer and HyperlinkedModelSerializer?

The HyperlinkedModelSerializer class is similar to the ModelSerializer class except that it uses hyperlinks to represent relationships, rather than primary keys. By default the serializer will include a url field instead of a primary key field.

Is serialization necessary in django?

It is not necessary to use a serializer. You can do what you would like to achieve in a view. However, serializers help you a lot. If you don't want to use serializer, you can inherit APIView at a function-based-view.

How do you use the serializer method field?

SerializerMethodField is a read-only field, which gets its value by calling a method on the serializer class that it is attached to. It can be used to attach any kind of data to the serialized presentation of the object. SerializerMethodField gets its data by calling get_<field_name> .


1 Answers

Solution-1: Using Model2Serializer in a Model1's SerializerMethodField()

In this method, we define a model2_data SerializerMethodField() field in the Model1Serializer. There, we will first fetch all the Model2 objects using the current Model1 object. Then we initialize the Model2Serializer with many=True argument and pass all the obtained Model2 instances. To return the serialized representation of Model2 objects, we access the .data property.

class Model1Serializer(serializers.ModelSerializer):

    model2_data = serializers.SerializerMethodField() # define separate field

    class Meta:
        model = Model1
        fields = [.., 'model2_data']

    def get_model2_data(self, obj):
        # here write the logic to get the 'Model2' objects using 'obj'

        # initialize the 'Model2Serializer'
        model2_serializer = Model2Serializer(model2_objs, many=True)

        # return the serialized representation of 'Model2' objs
        return model2_serializer.data

Solution-2: Overriding the retrieve method

Another option is to override the retrieve method and add the model2_data to your response along with original response.

class MyView(generics.RetrieveAPIView):

    serializer_class = Model1Serializer

    def retrieve(self, request, *args, **kwargs):
        instance = self.get_object()
        serializer = self.get_serializer(instance)

        # get the original serialized data
        serialized_data = serializer.data

        # get the 'Model2' objects using 'serializer.instance'
        model2_serializer = Model2Serializer(model2_objs, many=True)
        model2_data = model2_serializer.data

        # add the serialized representation of `Model2` objs
        serialized_data['model2_data'] = model2_data

        return Response(serialized_data)

PS: I know these solutions are not clean. Had the two models been related, we could have approached the problem in a more cleaner way.

like image 136
Rahul Gupta Avatar answered Nov 03 '22 01:11

Rahul Gupta