Django REST Framework: The powers of a Serializer (1)

aravindas4

Aravinda S Holla

Posted on November 29, 2020

Django REST Framework: The powers of a Serializer (1)

Water has been taken for granted. - Jan Eliasson

DRF's Serializer has been proved to be a killing feature.

Here I am going to share details of updating a Foreign key object data while updating a reverse relation object using serializer.

The point here is that, while we usually use foreign key fields in the serializer for reading operation, we can also use them to write operations.

Update FK object data:

Let's consider a scenario.

Where we have an account, to which loan applications can be submitted. While approving an application, we need to collect the approved_amount and reason.

class Account(models.Model):
    account_number = models.CharField(max_length=255)
    approved_amount = models.PositiveIntegerField(default=0)
    reason = models.CharField(max_length=255, null=True, blank=True)

    def __str__(self):
        return self.account_number


class LoanApplication(models.Model):

    class Status(models.TextChoices):
        SUBMITTED = 'SUBMITTED', 'Submitted',
        REJECTED = 'REJECTED', 'Rejected'
        APPROVED = 'APPROVED', 'Approved'

    account = models.ForeignKey(Account, on_delete=models.CASCADE)
    status = models.CharField(
        max_length=255, choices=Status.choices, default=Status.SUBMITTED)

    def __str__(self):
        return str(self.account)
Enter fullscreen mode Exit fullscreen mode

The above requirement shall be done using only one API call.

As shown in the above code shots, we have approved_amount and reason in the Account model, whereas approval shall be done to the LoanApplication object.

Let's see how the serializer tackles the above problem.

As in the below shots, while approval, we collect the amount and reason in the same API. In serializer, just before updating LoanApplication, we separate Account data and update to the appropriate account, then proceed to update the loan application.

class AccountSerializer(serializers.ModelSerializer):

    class Meta:
        model = Account
        fields = '__all__'


class LoanApplicationSerializer(serializers.ModelSerializer):
    approved_amount = serializers.IntegerField(
        source='account.approved_amount')
    reason = serializers.CharField(source='account.reason')

    class Meta:
        model = LoanApplication
        exclude = ('account',)

    def update(self, instance, validated_data):
        account_data = validated_data.pop('account', None)
        if account_data:
            account_serializer = AccountSerializer(
                instance.account, data=account_data, partial=True)
            account_serializer.is_valid(raise_exception=True)
            account_serializer.save()

        return super().update(instance, validated_data)
Enter fullscreen mode Exit fullscreen mode

Links:

  1. Github code
💖 💪 🙅 🚩
aravindas4
Aravinda S Holla

Posted on November 29, 2020

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related