Dynamic serializer configuration for Django REST Framework - Shape your API responses at runtime.drf-shapeless-serializers revolutionizes API development by giving you runtime serializer superpowers. Instead of creating multiple serializer classes , configure everything on the fly with one serializer to rule them all.Now you can shape your serializers like Lego cubes - rearranging fields, nesting relationships, and transforming outputs dynamically with unlimited flexibility.
Project description
drf-shapeless-serializers
Motivation
Traditional Django REST Framework serializers often lead to what’s known as “serializer hell” - a situation where developers:
- Create numerous serializer variations for slightly different API endpoints
- Duplicate code for simple field variations
- Struggle with rigid and complex nested relationships
- Maintain sprawling serializer classes that become hard to manage
drf-shapeless-serializers was created to solve these pain points by introducing dynamic runtime configuration capabilities, allowing you to eliminate up to 80% of your serializer code while gaining unprecedented flexibility.
Documentation
https://drf-shapeless-serializers.readthedocs.io/en/latest/
Overview
drf-shapeless-serializers provides powerful mixins that extend Django REST Framework's serializers with dynamic configuration capabilities. By inheriting from our base classes, you can select fields at runtime, rename output keys dynamically, modify field attributes per-request, and add configured nested relationships on-the-fly.
Installation
pip install drf-shapeless-serializers
Add to your Django settings:
INSTALLED_APPS = [
# ... other apps
'shapeless_serializers',
]
Usage
Basic Setup
- Define your shapeless serializer:
from shapeless_serializers.serializers import ShapelessModelSerializer
class UserSerializer(ShapelessModelSerializer):
class Meta:
model = User
fields = '__all__'
class AuthorSerializer(ShapelessModelSerializer):
class Meta:
model = Author
fields = '__all__'
class BookSerializer(ShapelessModelSerializer):
class Meta:
model = Book
fields = '__all__'
- Configure dynamically in views:
Instead of passing dictionaries, you now pass instantiated serializers into the
nestedparameter, allowing for a more Pythonic and type-safe configuration.
@api_view(['GET'])
def book_detail(request, pk):
book = Book.objects.get(pk=pk)
serializer = BookSerializer(
book,
fields=['id', 'title', 'price', 'author'],
rename_fields={'price': 'retail_price', 'id': 'book_id'},
nested={
'author': AuthorSerializer(
fields=['id', 'bio', 'user'],
rename_fields={'bio': 'biography'},
nested={
'user': UserSerializer(fields=['id', 'username', 'email'])
}
)
}
)
return Response(serializer.data)
Feature Highlights
1. Class-Based View (CBV) Support
The ShapelessViewMixin allows you to define dynamic configurations directly on your ViewSets. This keeps your view logic clean and centralized.
from shapeless_serializers.views import ShapelessViewMixin
class BookViewSet(ShapelessViewMixin, viewsets.ModelViewSet):
queryset = Book.objects.all()
serializer_class = BookSerializer
def get_serializer_fields(self):
if self.action == 'list':
return ['id', 'title', 'price']
return ['id', 'title', 'description', 'author', 'comments']
def get_serializer_nested(self):
if self.action == 'retrieve':
return {
'author': AuthorSerializer(fields=['name', 'bio']),
'comments': CommentSerializer(fields=['content', 'user'], many=True)
}
return {}
2. Field Selection
The fields parameter lets you cherry-pick exactly which fields to include.
AuthorSerializer(author, fields=['id', 'name', 'birth_date'])
3. Field Attributes
Pass standard DRF serializer params at runtime.
AuthorSerializer(
author,
field_attributes={
'bio': {'help_text': 'Author biography'},
'address': {'write_only': True}
}
)
4. Nested Relationships
Nested configuration supports unlimited depth. Each level can be customized with its own fields, renaming, and attributes.
AuthorSerializer(
author,
nested={
'books': BookSerializer(
fields=['title', 'publish_year', 'publisher'],
nested={
'publisher': PublisherSerializer(fields=['name', 'country'])
}
)
}
)
For extremely complex structures, the syntax remains readable:
serializer = DynamicBlogPostSerializer(
posts,
fields=["id", "title", "author", "comments"],
rename_fields={"id": "post_identifier"},
nested={
"author": DynamicAuthorProfileSerializer(
fields=["bio", "is_verified", "user"],
rename_fields={"bio": "author_biography"},
nested={
"user": UserSerializer(
fields=["id", "username"],
rename_fields={"username": "user_login"}
)
}
),
"comments": DynamicCommentSerializer(
fields=["id", "content", "user", "replies"],
instance=posts.comments.filter(is_approved=True, parent__isnull=True),
rename_fields={"content": "comment_text"},
nested={
"user": UserSerializer(fields=["id", "username"]),
"replies": DynamicCommentSerializer(
fields=["id", "content", "user"],
instance=lambda instance, ctx: instance.replies.filter(is_approved=True),
rename_fields={"content": "reply_text"}
)
}
)
}
)
5. Conditional Fields
Include fields based on runtime logic (like user permissions):
AuthorSerializer(
author,
conditional_fields={
'email': lambda instance, ctx: ctx['request'].user.is_staff
}
)
6. Inline Shapeless Model Serializers
Create serializers on-the-fly without defining a class—perfect for one-off needs:
serializer = InlineShapelessModelSerializer(
book,
model=Book,
fields=['title', 'author'],
nested={
'author': InlineShapelessModelSerializer(
model=Author,
fields=['name', 'bio']
)
}
)
When to Use
- Building public APIs with multiple versions.
- Projects needing different "views" of the same data (e.g., Summary vs. Detail).
- Rapidly evolving API requirements where creating new classes is a bottleneck.
- Any project suffering from "Serializer Bloat."
Contributing
We welcome contributions! Please check the CONTRIBUTING.md file.
License
This project is licensed under the MIT License. See the LICENSE file for details.
Acknowledgements
Inspired by the need for high-flexibility API systems. Special thanks to the Django REST Framework community.
Support Me
If you find this package useful, please consider supporting its development:
- USDT (TRC20):
TEitNDQMm4upYmNvFeMpxTRGEJGdord3S5 - USDT (BEP20):
0xc491a2ba6f386ddbf26cdc906939230036473f5d - BTC:
13X8aZ23pFNCH2FPW6YpRTw4PGxo7AvFkN
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file drf_shapeless_serializers-1.0.7.tar.gz.
File metadata
- Download URL: drf_shapeless_serializers-1.0.7.tar.gz
- Upload date:
- Size: 9.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
40229449a68fb02d8f911870d02bb391d508d35ea6e7a03892f213f5f1140b98
|
|
| MD5 |
f16cddcf1cecbfaf0ae577dbdb0a0f1d
|
|
| BLAKE2b-256 |
8d3844d1928dfbc395f62b99afd200b1f7e4b6129c5922759f3bb8cd8330e923
|
File details
Details for the file drf_shapeless_serializers-1.0.7-py3-none-any.whl.
File metadata
- Download URL: drf_shapeless_serializers-1.0.7-py3-none-any.whl
- Upload date:
- Size: 10.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9f6b17c3334e0d82461da68aa13f0b8f8d51d028aa712d3b7b97d6d8d57b3f78
|
|
| MD5 |
4f126ccc34084029d9cfc977430d58ee
|
|
| BLAKE2b-256 |
971089c0f6357058814fd23eab7b3a226a586c95929d81c758e2caaf22ce7b21
|