DEV Community

Cover image for Django REST Framework: The powers of a Serializer (1)
Aravinda S Holla
Aravinda S Holla

Posted on

2 1

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

Image of Datadog

Create and maintain end-to-end frontend tests

Learn best practices on creating frontend tests, testing on-premise apps, integrating tests into your CI/CD pipeline, and using Datadog’s testing tunnel.

Download The Guide

Top comments (0)

Image of Docusign

🛠️ Bring your solution into Docusign. Reach over 1.6M customers.

Docusign is now extensible. Overcome challenges with disconnected products and inaccessible data by bringing your solutions into Docusign and publishing to 1.6M customers in the App Center.

Learn more