Innovate anywhere, anytime withruncode.io Your cloud-based dev studio.
Django

Customizing Django REST API Serializers

2022-07-25

Adding extra fields to Serializers

# serializers.py
from rest_framework import serializers
from test_app.models import Product

class ProductSerializer(serializers.Serializer):
    product_id = serializers.IntegerField()
    product = serializers.SerializerMethodField('get_product_name')

    def get_product_name(self, obj):
        if obj.get("product_id"):
            obj_product = Product.objects.filter(id=obj.get("product_id")).first()
            if obj_product:
                return obj_product.name
        return None

# API views.py
from rest_framework.decorators  import api_view
from rest_framework.response import Response
from rest_framework import status
from test_app.serializers import ProductsSerializer

@api_view(['GET'])
def list_products(request):
    response_data = {}
    response_data["data"] = ProductSerializer(
                                    [{"program": i} for i in [1, 2, 3]],
                                   many=True
                                ).data
    return Response(response_data, status=status.HTTP_200_OK)

Passing extra arguments to Serializer Class in Django Rest Framework

Suppose we have serializer called 'CollegeStudentsSerializer' which should return all students, branches details of a logged-in user college

# serializers.py
from rest_framework import serializers
from test_app.models import Student, Branch

class StudentSerializer(serializers.ModelSerializer):

    class Meta:
        model = Student
        fields = ['id', 'first_name', 'last_name', 'branch']

class BranchSerializer(serializers.ModelSerializer):

    class Meta:
        model = Branch
        fields = ['id', 'name', 'code']

class CollegeDetailsSerializer(serializers.Serializer):
    students = serializers.SerializerMethodField('get_students')
    branches = serializers.SerializerMethodField('get_branches')

    def __init__(self, *args, **kwargs):
        context = kwargs.pop("context")
        self.college_id = context.get('college_id')
        super(CollegeDetailsSerializer, self).__init__(*args, **kwargs)

    def get_students(self, obj):
        return StudentSerializer(
                    Student.objects.filter(college_id=self.college_id),
                    many=True
                ).data

    def get_branches(self, obj):
        return BranchSerializer(
                    Branch.objects.filter(college_id=self.college_id),
                    many=True
                ).data

# API views.py
from rest_framework.decorators  import api_view
from rest_framework.response import Response
from rest_framework import status
from test_app.serializers import CollegeDetailsSerializer

@api_view(['GET'])
def students_list(request):
    response_data = {"data": []}
    if request.user and request.user.college_id:
        response_data["data"] = CollegeDetailsSerializer(
                                    context={"college_id": request.user.college_id},
                                    many=True
                                ).data
    return Response(response_data, status=status.HTTP_200_OK)