Thinker
Thinker

Reputation: 5366

Foreign key serializer update method

I have following models:

class Card(models.Model):
    thing = models.CharField(max_length=50, blank=True, null = True, )

class Responsibility(models.Model):
    name = models.CharField(max_length=50, blank=True, null=True, )
    card = models.ForeignKey(Card, related_name='responsibilities', blank=True, null=True, on_delete=models.CASCADE)

class Collaborator(models.Model):
    name = models.CharField(max_length=50, blank=True, null=True, )
    card = models.ForeignKey(Card, related_name='collaborators', blank=True, null=True, on_delete=models.CASCADE)

And my serializers:

class CollaboratorSerializer(serializers.ModelSerializer):

    class Meta:
        model = Collaborator
        fields = '__all__'

class ResponsibilitySerializer(serializers.ModelSerializer):
    class Meta:
        model = Responsibility
        fields = '__all__'      


class CardSerializer(serializers.ModelSerializer):

    responsibilities = ResponsibilitySerializer(many=True,)
    collaborators = CollaboratorSerializer(many=True,)

    class Meta:
        model = Card
        fields = '__all__'

    def create(self, validated_data):
        responsibilities_data = validated_data.pop('responsibilities')
        collaborators_data = validated_data.pop('collaborators')

        card = Card.objects.create(**validated_data)
        for responsibility_data in responsibilities_data:
            Responsibility.objects.create(card=card, **responsibility_data)
        for collaborator_data in collaborators_data:
            Collaborator.objects.create(card=card, **collaborator_data)
        return card

Create and get are successful, I am not sure how to implement update() method for Card. Sample request.data looks like following:

{u'collaborators': [{u'id': 8, u'card': 12, u'name': u''}, {u'name': u''}, {u'name': u''}], u'responsibilities': [{u'name': u'Name'}, {u'name': u'Age'}, {u'name': u'Address'}], u'id': 12, u'thing': u'Reader'}

In my update method, I would like to first delete all responsibilities and collaborators of that specific card, and then create fresh from the data received.

What I have so far:

def update(self, instance, validated_data):
    instance.responsibilities.all().delete()
    instance.collaborators.all().delete()
    .. NOT SURE ABOUT THIS PART ..

Upvotes: 0

Views: 383

Answers (2)

Andrei Berenda
Andrei Berenda

Reputation: 1986

This link https://github.com/encode/django-rest-framework/blob/master/docs/topics/writable-nested-serializers.md can help you. This package is a very good for update and create related field in serializer without overwrite methods. I hope it will be usefull for you

Upvotes: 0

Satendra
Satendra

Reputation: 6865

You can override update method of ModelSerializer

class CardSerializer(serializers.ModelSerializer):

    ...

    def update(self, instance, validated_data):
        # do stuff here
        instance.collaborators.all().delete()
        instance.responsibilities.all().delete()

        res = validated_data.get('responsibilities', [])
        aList = [Responsibility(**vals) for vals in res]
        Responsibility.objects.bulk_create(aList)

        # same goes for collaborators

Upvotes: 1

Related Questions