Skip to content Skip to sidebar Skip to footer

ManyToMany Relation Custom Serializer

Assume I have two models: class IPAddress(models.Model): address = models.CharField() class Rule(models.Model): name = models.CharField() ips = models.ManyToMany(IPAdd

Solution 1:

If you need to return an instance of Rule in following format:

{
"name":"Foo",
"ips":["192.168.1.40", "4.4.4.4", "8.8.8.8"]
}

You could create a RuleSerializer and use SlugRelatedField.

SlugRelatedField only works with the objects which already exist. Since you would be creating objects as well, you could modify the to_internal_value implementation to create the objects which doesn't exist (referenced from here):

class CreatableSlugRelatedField(serializers.SlugRelatedField):

    def to_internal_value(self, data):
        try:
            return self.get_queryset().get_or_create(**{self.slug_field: data})[0]
        except ObjectDoesNotExist:
            self.fail('does_not_exist', slug_name=self.slug_field, value=smart_text(data))
        except (TypeError, ValueError):
            self.fail('invalid')

class RuleSerializer(serializers.ModelSerializer):

    ips = serializers.CreatableSlugRelatedField(
        many=True,
        slug_field='address' # this is the ip address
        queryset=IPAddress.objects.all()
    )

    class Meta:
         model = Rule
         fields: ('name', 'ips')

UPDATE: Based on the comments in the question:

I could not change the request I get and the response I must send

But if you could then use nested serializers though your representation would need to change slightly:

{
    "name": "Foo",
    "ips": [
         {"address": "192.168.1.40"}, 
         {"address": "4.4.4.4"}, 
         {"address": "8.8.8.8"}
    ]
}

and, then the nested serializers (more documentation here):

class IPAddressSerializer(serializers.ModelSerializer):

     class Meta:
         model = IPAddress
         fields: ('address',)

class RuleSerializer(serializers.ModelSerializer):

    ips = IPAddressSerializer(many=True)

    class Meta:
         model = Rule
         fields: ('name', 'ips')

Post a Comment for "ManyToMany Relation Custom Serializer"