Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Initializing variables in init when using Django Rest Framework for list serializers

I would like to have a serializer where one of the fields in the serializer depends on a value created in the init method.

I have tried to do something like the following:

class MySerializer(serializers.ModelSerializer):
   the_field_value = serializers.SerializerMethodField()
   another_field_value = serializers.SerializerMethodField()

class Meta:
    model = MyModel
    fields = ('id', 'the_field_value', 'another_field_value')

def get_the_field_value(self, obj):
    return "{0} ({1}) {2}".format(obj.name, obj.other_name, self.random_id)

def get_another_field_value(self, obj):
    return "{0} ({1}) {2}".format(obj.other_other_name, obj.other_name, self.random_id)

def __init__(self, *args, **kwargs):
    super(MySerializer, self).__init__(*args, **kwargs)
    self.random_id = randint(1, 5)

The issue is when using a list serializer the random_id is the same for every list item.

How can I specify an init method to be run for each list item?

Updated with a more detailed example.

like image 861
oowowaee Avatar asked Mar 12 '23 09:03

oowowaee


2 Answers

That's right, because the __init__ will be called just one time when you create an instance, but if you do it:

class MySerializer(serializers.ModelSerializer):
    the_field_value = serializers.SerializerMethodField()

    class Meta:
        model = MyModel
        fields = ('id', 'the_field_value')

    def get_the_field_value(self, obj):
        return "{0} ({1}) {2}".format(obj.name, obj.other_name, randint(1, 5))

you will get the random value on a list. Hope that it helps you.

like image 152
Vladir Parrado Cruz Avatar answered Apr 07 '23 14:04

Vladir Parrado Cruz


I think that you want to use the many init method which allows you customize the initialization of a list of objects on a per object basis. It's not very clear from the documentation exactly how it's supposed to be work, but it seems like you can customize the initialization of a list of objects on a per object basis -- perhaps something like this...?

class MySerializer(serializers.ModelSerializer):
    # all your fields and get methods...

    def random_init(self):
        return randint(1,5)

    @classmethod
    def many_init(cls, *args, **kwargs):
        # Instantiate the child serializer.
        kwargs['child'] = cls()
        # add the random value
        kwargs['random_id'] = cls.random_init()
        # Instantiate the parent list serializer.
        return MySerializer(*args, **kwargs)

    def __init__(self, *args, **kwargs):
        super(MySerializer, self).__init__(*args, **kwargs)
        self.random_id = kwargs.get('random_id', self.random_init() )
like image 34
Mark Chackerian Avatar answered Apr 07 '23 14:04

Mark Chackerian