Using SerializerMethodField in Django REST Framework
Last updated 4 months, 2 weeks ago | 440 views 75 5

In Django REST Framework, a ModelSerializer
typically maps model fields to serializer fields automatically. But what if you want to include a computed or dynamic value that isn’t a direct field on your model?
That’s where SerializerMethodField
comes in.
What is SerializerMethodField
?
SerializerMethodField
is a read-only field that gets its value by calling a method on the serializer class. This method lets you compute or customize a value at runtime based on the serialized object or request context.
It’s perfect for:
-
Custom computed fields
-
Conditional data
-
Related model logic
Syntax
from rest_framework import serializers
class MySerializer(serializers.ModelSerializer):
custom_field = serializers.SerializerMethodField()
class Meta:
model = MyModel
fields = ['id', 'name', 'custom_field']
def get_custom_field(self, obj):
return obj.name.upper()
-
The method name must be
get_<field_name>
-
The method receives the instance (
obj
) being serialized
Example: Book and Author
models.py
class Author(models.Model):
name = models.CharField(max_length=100)
class Book(models.Model):
title = models.CharField(max_length=100)
author = models.ForeignKey(Author, on_delete=models.CASCADE)
pages = models.IntegerField()
serializers.py
class BookSerializer(serializers.ModelSerializer):
author_name = serializers.SerializerMethodField()
is_lengthy = serializers.SerializerMethodField()
class Meta:
model = Book
fields = ['title', 'author_name', 'pages', 'is_lengthy']
def get_author_name(self, obj):
return obj.author.name
def get_is_lengthy(self, obj):
return obj.pages > 300
Sample Output
{
"title": "Django Mastery",
"author_name": "Jane Austen",
"pages": 350,
"is_lengthy": true
}
Using Context in SerializerMethodField
You can also access the serializer context, such as the request user.
class BookSerializer(serializers.ModelSerializer):
is_favorite = serializers.SerializerMethodField()
class Meta:
model = Book
fields = ['title', 'is_favorite']
def get_is_favorite(self, obj):
user = self.context['request'].user
return obj in user.favorite_books.all()
When instantiating the serializer:
BookSerializer(book_instance, context={'request': request})
Nested Use Case
class AuthorSerializer(serializers.ModelSerializer):
book_count = serializers.SerializerMethodField()
class Meta:
model = Author
fields = ['id', 'name', 'book_count']
def get_book_count(self, obj):
return obj.book_set.count()
This will return how many books the author has written, even though book_count
isn't a model field.
✅ Benefits
Benefit | Description |
---|---|
Custom logic | Compute values based on the object |
Dynamic behavior | Adjust based on user, request, or time |
Cleaner API | Keep models lean while exposing useful data |
⚠️ Common Pitfalls
Pitfall | Solution |
---|---|
❌ Missing get_<field_name> method |
Ensure the method name matches the field |
❌ Cannot write to field | This is a read-only field; use Serializer logic for writing |
❌ Forgetting to pass context | Always pass context={'request': request} if needed |
❌ Expensive DB calls | Avoid calling .count() or .all() in loops; use .annotate() or prefetching when needed |
Advanced Example: Conditional Discount
class ProductSerializer(serializers.ModelSerializer):
discount_price = serializers.SerializerMethodField()
class Meta:
model = Product
fields = ['name', 'price', 'discount_price']
def get_discount_price(self, obj):
user = self.context['request'].user
if user.is_staff:
return obj.price * 0.8
return obj.price
Full Working Example
models.py
class Book(models.Model):
title = models.CharField(max_length=100)
pages = models.IntegerField()
published_date = models.DateField()
serializers.py
class BookSerializer(serializers.ModelSerializer):
is_new_release = serializers.SerializerMethodField()
class Meta:
model = Book
fields = ['title', 'pages', 'published_date', 'is_new_release']
def get_is_new_release(self, obj):
from datetime import date, timedelta
return obj.published_date >= date.today() - timedelta(days=30)
Output
{
"title": "Learn Django",
"pages": 250,
"published_date": "2025-05-01",
"is_new_release": true
}
Best Practices
Best Practice | Why |
---|---|
✅ Keep logic in model if reusable | Improves reusability and testability |
✅ Use .annotate() for query-heavy fields |
Avoids performance issues |
✅ Pass context when needed | For user-aware or request-specific data |
✅ Avoid writing heavy logic inside serializer method | Delegate to service layers if complex |
✅ Summary
Feature | Value |
---|---|
Type | SerializerMethodField() |
Use | Add custom, read-only fields |
Input | Instance (obj ) and optionally self.context |
Output | Any computed value (string, number, list, etc.) |
Common Use Cases | Derived fields, conditional logic, extra metadata |
Conclusion
SerializerMethodField
is a powerful feature in Django REST Framework that allows you to expose custom, dynamic, or computed fields without cluttering your models. Use it when you need flexibility in what your serializers output—whether it’s user-specific logic, conditional formatting, or extra metadata.