{"id":34498059,"url":"https://github.com/loopwerk/drf-action-serializers","last_synced_at":"2026-03-15T04:44:15.896Z","repository":{"id":297686501,"uuid":"997618062","full_name":"loopwerk/drf-action-serializers","owner":"loopwerk","description":"An easy way to use different serializers for different actions and request methods in Django REST Framework","archived":false,"fork":false,"pushed_at":"2025-11-12T10:33:40.000Z","size":74,"stargazers_count":19,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-11-12T12:16:17.370Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/loopwerk.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":"loopwerk","buy_me_a_coffee":"loopwerk"}},"created_at":"2025-06-06T20:51:56.000Z","updated_at":"2025-11-12T10:33:34.000Z","dependencies_parsed_at":null,"dependency_job_id":"e4d1c9a0-8a43-4af5-8846-0809a7ff163c","html_url":"https://github.com/loopwerk/drf-action-serializers","commit_stats":null,"previous_names":["loopwerk/drf-action-serializers"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/loopwerk/drf-action-serializers","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/loopwerk%2Fdrf-action-serializers","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/loopwerk%2Fdrf-action-serializers/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/loopwerk%2Fdrf-action-serializers/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/loopwerk%2Fdrf-action-serializers/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/loopwerk","download_url":"https://codeload.github.com/loopwerk/drf-action-serializers/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/loopwerk%2Fdrf-action-serializers/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":27992755,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-12-23T02:00:07.087Z","response_time":69,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-12-24T01:52:39.174Z","updated_at":"2026-03-15T04:44:15.887Z","avatar_url":"https://github.com/loopwerk.png","language":"Python","readme":"# drf-action-serializers\n\n**An easy way to use different serializers for different actions and request methods in Django REST Framework**\n\nImagine a simple Django REST Framework serializer and view like this:\n\n```python\nfrom rest_framework import serializers\nfrom rest_framework import viewsets\nfrom .models import Post\n\nclass PostSerializer(serializers.ModelSerializer):\n    class Meta:\n        model = Post\n        fields = \"__all__\"\n\nclass PostViewSet(viewsets.ModelViewSet):\n    serializer_class = PostSerializer\n\n    def get_queryset(self):\n        return Post.objects.all()\n```\n\nThe `PostSerializer` class is used for everything: the list of posts, retrieving a single post, the payload when creating or updating a post, and the response when creating or updating a post.\n\nI find that this is often not what I want; for example I often want a simple version of the model to be returned in the list endpoint (`/posts/`), while the full model is returned in the retrieve endpoint (`/posts/{post_id}/`). And I also often want that the _input_ serializer is different from the _output_ serializer, when creating or updating something.\n\nAnd when you add extra router actions to your ViewSets and you want to use different serializers for them as well? Things are getting complicated and messy real fast.\n\nThat’s where drf-action-serializer comes in. Now your view can look like this:\n\n```python\nclass PostViewSet(ActionSerializerModelViewSet):\n    serializer_class = PostDetailSerializer\n    list_serializer_class = PostListSerializer\n    write_serializer_class = PostWriteSerializer\n```\n\nAnd just like that you’re using a different serializer for the list action, and for the create and update actions.\n\nOr you can get super specific, like this:\n\n```python\nclass PostViewSet(ActionSerializerModelViewSet):\n    list_read_serializer_class = PostListSerializer\n    retrieve_read_serializer_class = PostDetailSerializer\n    create_write_serializer_class = PostWriteSerializer\n    create_read_serializer_class = PostListSerializer\n    update_write_serializer_class = PostWriteSerializer\n    update_read_serializer_class = PostDetailSerializer\n```\n\nNow you’re using different input and output serializers as well!\n\n## Installation and usage\n\nInstall the package:\n\n```bash\n$ uv add drf-action-serializers\n```\n\nAnd then use its ViewSets like `ActionSerializerModelViewSet`, `ActionSerializerReadOnlyModelViewSet`, and `ActionSerializerGenericViewSet`, instead of Django REST Framework’s built-in ViewSets.\n\n```python\nfrom drf_action_serializers import viewsets\n\nclass PostViewSet(ActionSerializerModelViewSet):\n    retrieve_serializer_class = PostDetailSerializer\n    list_serializer_class = PostListSerializer\n    create_write_serializer_class = PostCreateSerializer\n    create_read_serializer_class = PostListSerializer\n    update_write_serializer_class = PostUpdateSerializer\n    update_read_serializer_class = PostListSerializer\n```\n\nNote: this package is built on top of Django Rest Framework, so it assumes that Django Rest Framework is installed and added to your project [as documented](https://www.django-rest-framework.org/#installation).\n\n## How it works\n\nWhen your view needs a serializer, drf-action-serializers looks at two things:\n\n1. **The action** — the ViewSet action being performed, like `list`, `retrieve`, `create`, `update`, `partial_update`, or any custom action you've added via `@action`.\n2. **The method** — either `read` (for safe HTTP methods: GET, HEAD, OPTIONS) or `write` (for unsafe HTTP methods: POST, PUT, PATCH, DELETE).\n\nIt then checks for a matching serializer property on your ViewSet in the following order, returning the first one it finds:\n\n| Priority | Property                             | Example                         |\n| -------- | ------------------------------------ | ------------------------------- |\n| 1        | `{action}_{method}_serializer_class` | `create_write_serializer_class` |\n| 2        | `{method}_serializer_class`          | `write_serializer_class`        |\n| 3        | `{action}_read_serializer_class`     | `create_read_serializer_class`  |\n| 4        | `{action}_serializer_class`          | `create_serializer_class`       |\n| 5        | `read_serializer_class`              |                                 |\n| 6        | `serializer_class`                   |                                 |\n\nSo for a `POST /posts/` request (action=`create`, method=`write`), the lookup order is: `create_write_serializer_class` → `write_serializer_class` → `create_read_serializer_class` → `create_serializer_class` → `read_serializer_class` → `serializer_class`.\n\nThis means you can be as specific or as general as you want. Setting `write_serializer_class` applies to all write operations, while `create_write_serializer_class` only applies to create. The most specific match always wins.\n\n### partial_update fallback\n\nThe `partial_update` action (PATCH requests) automatically falls back to `update` properties if no `partial_update`-specific property is found. So if you define `update_write_serializer_class`, it will also be used for PATCH requests — no need to define both.\n\n### Custom actions\n\nThis works with custom `@action` decorators too. If you have an action named `publish`, you can define `publish_serializer_class`, `publish_read_serializer_class`, `publish_write_serializer_class`, and so on.\n\n## drf-spectacular support\n\nIf you use drf-spectacular, then install the following optional package:\n\n```bash\n$ uv add drf-action-serializers[spectacular]\n```\n\nThen add the following to `settings.py` and it’s automatically used:\n\n```python\nREST_FRAMEWORK = {\n    \"DEFAULT_SCHEMA_CLASS\": \"drf_action_serializer.spectacular.ActionSerializerAutoSchema\",\n}\n```\n\n## Tests\n\nUnit tests can be run with `uv run pytest`.\n\n## About Feature Requests\n\nThis project is feature-complete — it does what I needed it to do, and I’m not actively looking to expand its functionality.\n\nI’m not accepting feature requests via issues. Please understand that asking for new features is essentially asking for free work — not just to build something, but to maintain it over time. And since I don’t personally need those features, I’m unlikely to invest time in them.\n\nIf you’d like to add a new feature, you’re welcome to open a pull request. Just know that I’ll evaluate it carefully, because even merged contributions become part of what I maintain. To avoid spending time on a PR that may not be accepted, I recommend starting a discussion first — that way we can talk through the idea and see if it fits.\n\nThis approach helps me avoid burnout and keep the project sustainable. Thanks for understanding!\n\n## Credits\n\nMany thanks to [rest-framework-actions](https://github.com/AlexisMunera98/rest-framework-actions) and [drf-rw-serializers](https://github.com/vintasoftware/drf-rw-serializers) for the inspiration.\n","funding_links":["https://github.com/sponsors/loopwerk","https://buymeacoffee.com/loopwerk"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Floopwerk%2Fdrf-action-serializers","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Floopwerk%2Fdrf-action-serializers","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Floopwerk%2Fdrf-action-serializers/lists"}