Rest Framework
Serizaliers

Django Rest Framework Serializers - Panduan Lengkap

1. Dasar Serializer

Serializer Dasar

# serializers.py
from rest_framework import serializers
 
class ProductSerializer(serializers.Serializer):
    name = serializers.CharField(max_length=100)
    price = serializers.DecimalField(max_digits=10, decimal_places=2)
    description = serializers.CharField(required=False)
 
    def create(self, validated_data):
        return Product.objects.create(**validated_data)
 
    def update(self, instance, validated_data):
        instance.name = validated_data.get('name', instance.name)
        instance.price = validated_data.get('price', instance.price)
        instance.description = validated_data.get('description', instance.description)
        instance.save()
        return instance

ModelSerializer

# serializers.py
from rest_framework import serializers
from .models import Product
 
class ProductModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = Product
        fields = ['name', 'price', 'description']
        # atau gunakan fields = '__all__' untuk semua field

2. Tipe Field Serializer

Text Fields

# Field untuk data teks
name = serializers.CharField(
    max_length=100,
    required=True,
    allow_blank=False
)
description = serializers.CharField(
    style={'base_template': 'textarea.html'}
)
email = serializers.EmailField()

Number Fields

# Field untuk angka
price = serializers.DecimalField(
    max_digits=10,
    decimal_places=2,
    min_value=0
)
quantity = serializers.IntegerField(min_value=1)
rating = serializers.FloatField(min_value=0, max_value=5)

Relational Fields

# Field untuk relasi
category = serializers.PrimaryKeyRelatedField(queryset=Category.objects.all())
tags = serializers.StringRelatedField(many=True)
owner = serializers.HyperlinkedRelatedField(
    view_name='user-detail',
    read_only=True
)

3. Validasi Serializer

Validasi di Level Field

class ProductSerializer(serializers.ModelSerializer):
    def validate_name(self, value):
        if value.isdigit():
            raise serializers.ValidationError(
                'Nama tidak boleh berupa angka'
            )
        return value

Validasi Serializer Level

class ProductSerializer(serializers.ModelSerializer):
    def validate(self, data):
        if data['discount_price'] >= data['price']:
            raise serializers.ValidationError(
                'Harga diskon harus lebih kecil dari harga asli'
            )
        return data

4. Penggunaan di Views

Function Based Views

from rest_framework.decorators import api_view
from rest_framework.response import Response
 
@api_view(['POST'])
def product_create(request):
    serializer = ProductSerializer(data=request.data)
    if serializer.is_valid():
        serializer.save()
        return Response(serializer.data, status=201)
    return Response(serializer.errors, status=400)

Class Based Views

from rest_framework import generics
 
class ProductCreateAPIView(generics.CreateAPIView):
    queryset = Product.objects.all()
    serializer_class = ProductSerializer

5. Nested Serializer

class CategorySerializer(serializers.ModelSerializer):
    class Meta:
        model = Category
        fields = ['id', 'name']
 
class ProductSerializer(serializers.ModelSerializer):
    category = CategorySerializer()
 
    class Meta:
        model = Product
        fields = ['id', 'name', 'price', 'category']

6. Tips Penggunaan Serializer

  1. Custom Field
class ProductSerializer(serializers.ModelSerializer):
    discount_percentage = serializers.SerializerMethodField()
 
    def get_discount_percentage(self, obj):
        return ((obj.price - obj.discount_price) / obj.price) * 100
  1. Read Only Fields
class ProductSerializer(serializers.ModelSerializer):
    class Meta:
        model = Product
        fields = '__all__'
        read_only_fields = ['created_at', 'updated_at']
  1. Dynamic Fields
class DynamicProductSerializer(serializers.ModelSerializer):
    class Meta:
        model = Product
        fields = '__all__'
 
    def __init__(self, *args, **kwargs):
        fields = kwargs.pop('fields', None)
        super().__init__(*args, **kwargs)
 
        if fields:
            allowed = set(fields)
            existing = set(self.fields)
            for field_name in existing - allowed:
                self.fields.pop(field_name)