drf-extensions is six missing pieces of Django REST Framework, and its release process is in the README
DRF-extensions is a collection of custom extensions for Django REST Framework
At a glance
- What is it?
- drf-extensions is a collection of extensions for Django REST Framework covering detail serializers, response caching, conditional requests, custom cache keys, nested routes and bulk operations. The version matrix spans Django 3.2 to 6.0 and Python 3.9 to 3.14, and the repository documents its own release checklist in unusual detail.
- Who is it for?
- Adopt drf-extensions if you have DRF viewsets that repeat the same detail-serializer selection or make the same conditional request logic by hand, since those mixins remove code rather than adding a framework. Skip it if your API is small enough that one generic view covers it.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 93 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on November 7, 2026, and from our analysis. They are not legal advice.
Star history
- chibisov/drf-extensions1,548 ★ · -1
| Repository | 2026-10-19 | 2026-11-07 |
|---|---|---|
| chibisov/drf-extensions | 1.5k | 1.5k |
-1 Stars in the last 19 days, measured from the daily GitHub snapshot. Compare with other projects
Editorial analysis
Six features, all filling gaps in DRF itself
drf-extensions describes itself as a collection of custom extensions for Django REST Framework, and the feature list is six items.
DetailSerializerMixin is the first. DRF lets you name a serializer per view, so a viewset with a list action and a detail action needs two serializer classes and code to choose between them. That mixin takes a serializer class name per action instead, which is a small thing that removes a repeated conditional from every viewset you write.
Caching is the second, and it comes with conditional requests and customizable key construction for both. Those three are really one feature described three ways: cached responses need an ETag or a Last-Modified value, conditional requests need to compare an incoming If-None-Match against it, and both need a key derived from the request. Doing that by hand means the same three lines in every view, and the interesting part is the key construction, because a naive key of path plus user misses every parameter that changes the response.
Nested routes and bulk operations are the remaining two. Nested routes let a detail view have children, and bulk operations let one request act on several objects rather than requiring a client loop.
What is deliberately absent is as informative as what is present. There is no filtering library, no pagination style and no serializer framework here. Those live elsewhere, and this package stays inside the space of things DRF should arguably have shipped.
That is a coherent scope. A collection of mixins is easy to adopt one at a time, since each is independent, and nothing here changes how DRF works if you do not use it.
The support matrix is explicit about versions
The requirements section lists what is actually tested rather than what is theoretically compatible, which is the more useful information.
Python is tested on 3.9, 3.10, 3.11, 3.12, 3.13 and 3.14. Django REST Framework is tested on 3.12, 3.13, 3.14, 3.15 and 3.16. Django itself is tested from 3.2 to 6.0. django-filter is tested at 2.1.0 and above.
Those ranges are wide for a library of this age, and they are the kind of thing that only stays true with work, so the last push on 2026-08-06 after the 0.8.0 release in April 2025 is worth noting.
Installation is one command from PyPI, with a source archive as the alternative:
pip3 install drf-extensionsThe setup.py file gives the runtime floor differently from the tested matrix, which is the usual and correct distinction. `install_requires` names `djangorestframework>=3.10.3`, `packaging>=24.1` and `Django>=3.2,<6.2`.
So the installable range is wider than the tested range at the bottom end for DRF, and it stops at Django 6.2 rather than 6.0. If you are on Django 6.1 or 6.2, the package will install on a version outside the tested matrix, which is worth knowing before you put it in a production requirements file.
The `packaging` dependency is worth a second look. It is there for version handling rather than for anything API related, which is the usual reason a small library pulls it in, and pinning it at 24.1 or newer keeps the version comparison behaviour consistent.
The release process is written down, including the gh-pages merge
The README contains a section titled Publishing new releases with a numbered checklist, and it is more detailed than most projects bother with.
The version lives in `rest_framework_extensions/__init__.py`, incremented as a plain assignment. Release notes move from the Development version section into a new section with a date, and every `New in DRF-extensions development version` note in the documentation is replaced with the actual version number. The documentation is rebuilt, the tests are run, and the commit is made with the message being the version.
Then tagging and pushing, followed by a step that catches people out: merge master into the gh-pages branch with `--no-ff` and push it, because the documentation site is built from that branch. A release without that step publishes the library and leaves the website a version behind.
Publishing to PyPI is the last step, and the command is `python setup.py publish`.
That last point connects to something odd in setup.py. There is no entry point for it; instead the script checks whether the last command line argument is `publish`, and if so it shells out to `sdist upload` and `bdist_wheel upload`, prints a reminder to tag the version, and exits without running `setup()`. That publishing path should be checked against the setuptools version in use.
This is a clear sign that the publishing documentation and tooling should be checked together.
The rest of the contributor process is conventional. New features should be documented, tested, implemented and pushed, and the documentation convention is that a pull request adds a Development version section with anchors so the release notes stay navigable.
Testing through tox, with paths that show the package layout
The development section is a set of tox invocations, and the paths in them reveal how the package is organised.
The base run is `tox -- tests_app`, and there is a variant for an exact environment, `tox -e py38 -- tests_app`, though the tested matrix has since moved well past Python 3.8.
Recreating the environments is `tox --recreate -- tests_app`. Custom arguments pass through, so `tox -- tests_app --verbosity=3` sets the verbosity. For interactive debugging there is `tox -- tests_app --processes=0 --nocapture`, which serialises the run so pdb works.
The two most useful commands are the last two. You can run a single test case by full dotted path:
$ tox -- tests_app.tests.unit.mixins.tests:DetailSerializerMixinTest_serializer_detail_classor a whole module:
$ tox -- tests_app.tests.unit.mixins.testsThat path structure is the documentation for the package itself. `tests_app.tests.unit.mixins.tests` tells you the features live under `mixins`, which matches the feature list, since every extension here is a mixin.
Documentation is built with `make build_docs` from a `GNUmakefile`, and `make watch_docs` rebuilds on changes after installing watchdog.
The repository also carries a SECURITY.md and AUTHORS.md, and the contributors and backers are handled through Open Collective with Tidelift as the platform sponsor listed at the top.
Where drf-extensions is the wrong choice
Three cases.
If your API surface is small, one generic view plus a couple of serializers will cover it, and a package of mixins is dependency weight for no benefit. The features are worth their cost at the point where the same conditional appears in five view classes.
If you need something not in the list, you will find the boundary quickly. There is no filtering, no pagination, no throttling and no versioning here, and adding a second package for those means your DRF configuration is now spread across two sets of settings and two sets of release cycles.
If your project is on a Django or DRF combination outside the tested ranges, you are the compatibility tester. Django 6.1 and 6.2 install fine but are not in the tested matrix, and DRF below 3.12 is not either.
One inconsistency to be aware of before you depend on the licence. setup.py declares `license='BSD'` and the docker-compose style licence statements elsewhere are not present here, while the repository's recorded licence is MIT. If your compliance process needs a single answer, resolve which applies with the maintainer rather than assuming.
On cadence, the release history is irregular rather than dead. 0.7.0 shipped in February 2021, 0.7.1 in July 2021, and then nothing until 0.8.0 in April 2025, with commits continuing since. That gap is the honest signal about how much attention this package gets, and for a dependency that does jobs DRF does not, a long quiet period is safer than an active fork with breaking changes.
Editorial conclusion
Adopt drf-extensions if you have DRF viewsets that repeat the same detail-serializer selection or make the same conditional request logic by hand, since those mixins remove code rather than adding a framework. Skip it if your API is small enough that one generic view covers it. Verify first that your DRF version falls between 3.12 and 3.16 as tested, and note that setup.py declares a BSD licence while the repository licence is recorded as MIT.
Frequently asked questions
How do I install drf-extensions?
Run `pip3 install drf-extensions` from PyPI, or install the source archive directly from the GitHub master branch zip. The package requires Django REST Framework 3.10.3 or newer and Django between 3.2 and 6.2 at install time.
Which Django and DRF versions are tested?
Python 3.9 through 3.14, Django REST Framework 3.12 through 3.16, Django 3.2 through 6.0, and django-filter 2.1.0 or newer. The installable range in setup.py is wider, which means a version can install without being tested.
What does DetailSerializerMixin do?
It lets a viewset choose a different serializer class per action, so a list action and a detail action can each declare their own serializer instead of sharing one view-level declaration with conditional logic in each view.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/chibisov-drf-extensions)Star history chart for your README
[](https://hysenlabs.com/projects/chibisov-drf-extensions)Was this useful?