Framework
AltSchool/dynamic-rest avatar
AltSchool/dynamic-rest

dynamic-rest: graph-style relationships for Django REST Framework

Dynamic extensions for Django REST Framework

834 stars114 forksPythonMIT

At a glance

What is it?
DREST extends Django REST Framework with linked, sideloaded and embedded relationships, plus include and exclude parameters, so a client can shape a response the way it would shape a graph query. It is a drop-in replacement for the DRF classes, but the version numbers in the repository have not moved in a long while.
Who is it for?
Adopt dynamic-rest if your Django REST Framework API needs relationship endpoints, client-controlled include and exclude parameters, or a browsable directory panel, and your consumers can cope with a response format that is not plain DRF.
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?
Activity is slowing. The repository last received commits 6 months 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 October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Drop-in classes that change what a response contains

Dynamic REST, abbreviated DREST, extends Django REST Framework with API features that give a simple RESTful API the flexibility of a graph query language. The adoption path is the first thing to understand. DREST classes can be used as a drop-in replacement for the standard DRF classes, so a project already built on ModelSerializer and ModelViewSet swaps in DynamicModelSerializer and DynamicModelViewSet and keeps working. What changes is what a client can ask for. The feature list is linked relationships, sideloaded relationships, embedded relationships, inclusions, exclusions, filtering, sorting, a directory panel for the browsable API, and a set of optimisations. The project states it was originally written to complement Ember and its Ember Data, which is the clearest description of the design intent. A relationship in DREST is not a fixed foreign key field. It is something the client can traverse, eagerly load, or embed, depending on the request, which is the graph-query behaviour the package borrows.

Relationships come in three shapes, and the client picks

The linked relationship is the default and the foundation. A has-one relationship is represented as the value of the related object's ID, and a has-many relationship as a list of related object IDs. On top of that, DREST automatically includes relationship links for has-many relationships in the response, so a request for a user returns a links object pointing at the related collection, and DREST creates those relationship endpoints automatically with no additional code. The response for a user is shaped like this:

code
    GET /users/1/

and the has-many relationship gets its own endpoint, which a consumer can then call to obtain the related records. The second shape is sideloading, where relationships are loaded eagerly rather than lazily. Django already offers prefetch_related and select_related for this, and DREST exposes the same idea through the include[] query parameter, so a request for a user and their groups fetches both at once. The third is embedding, where the related records are inlined into the response body rather than referenced. The distinction between the three is what makes the package useful: a client that only needs identifiers gets a small payload, a client that needs everything gets it in one request, and a client that needs a record inline gets it inline.

Includes, exclusions and the query parameter that drives them

The include[] parameter is the mechanism that ties the three relationship shapes together, and it is the piece a consumer-facing API ends up documenting. A request for a user and their groups uses include[]=groups.*, and the response then carries the group records rather than only their IDs. Because the same parameter also drives embedding, a consumer changes one query string to move between lazy and eager loading. Exclusions work in the same direction and remove parts of the payload the client does not want. On top of that, the package adds filtering and sorting to the standard DRF set, and a directory panel for the browsable API, which is a browsable listing of the available endpoints and their fields, so a developer exploring the API can find the right route without reading the source. The optimisations in the feature list exist to keep the added flexibility from making every request expensive, since an API that can eagerly load arbitrary relationship graphs can otherwise turn into an unbounded number of database queries.

Installation is three settings changes and one pip command

The install path is short. First the package:

bash
    pip install dynamic-rest

or you add dynamic-rest to requirements.txt or setup.py. Then the app has to be registered, because DREST adds its own views and fields:

python
    INSTALLED_APPS = (
        ...
        'rest_framework',
        'dynamic_rest'
    )

The third step is optional and only applies if you want the directory panel, which means replacing DRF's browsable API renderer with the DREST one:

python
REST_FRAMEWORK = {
    'DEFAULT_RENDERER_CLASSES': [
        'rest_framework.renderers.JSONRenderer',
        'dynamic_rest.renderers.DynamicBrowsableAPIRenderer',
    ],
}

Leaving the renderer alone leaves you with the standard DRF browsable API and no directory panel. That is the right call if you do not want a DREST-specific renderer in front of your API consumers.

The tests package doubles as the demo application

The repository ships a tests package that also serves as a demo application, and that arrangement is the fastest way to evaluate the library. The hosted demo sits at dynamic-rest.herokuapp.com, and you can run it locally by cloning the repository and starting the demo server from the repository root:

bash
    git clone [email protected]:AltSchool/dynamic-rest.git
    cd dynamic-rest
bash
    make serve

The site then runs on localhost:9002. Sample data comes from a separate make fixtures target followed by a server restart, and the Makefile shows what that does under the hood, running manage.py migrate with the tests.settings module and then a manage.py initialize_fixture command, also against tests.settings. The Makefile also has docs, fixtures and PyPI upload targets, with a PORT variable defaulting to 9002 and a virtualenv created under./build. The benchmarks directory and the benchmarks.html file at the root indicate that query performance was measured at some point, though the README does not summarise the results.

The version numbers in the repository disagree with each other

This is the thing to check before you commit, and there is a real inconsistency rather than just an old project. The licence field of the project records MIT, and there are both a LICENSE.md and a LICENSE.txt at the root, while the setup.py classifier says BSD License. The stated requirements in the README are Python 3.6, 3.7 and 3.8, Django 2.2, 3.1 and 3.2, and Django REST Framework 3.11, 3.12 and 3.13. The setup.py classifiers, by contrast, list Python 3.7 through 3.11 and no Django or DRF versions at all. The setup.py version string is 2.3.0, and the tag history matches that: v2.2.0 on 2024-03-20, v2.2.1 and v2.3.0 both on 2024-03-26. The repository is not archived and the last push was on 2026-04-13, so there is work on the branch that post-dates the newest tag. Nobody has updated the compatibility documentation, and that documentation is what you will use to decide whether the library works with your Django and DRF versions.

MIT licensed, single maintainers, and a project with a past employer behind it

The maintainer list is three people, Anthony Leontiev, Savinay Nangalia and Christina D'Astolfo, all listed with tohigherground.com addresses, and the contributor credited is Ernesto González. That is worth noticing for a package of this age: it was maintained inside a company rather than by an individual hobbyist, and the same pattern shows up in the source layout, with a Dockerfile, a Procfile, an install_requires.txt read at packaging time, and a requirements.txt pinning old versions of tooling such as pytest-django, pytest-cov and Sphinx. The packaging is setuptools with find_packages, include_package_data turned on, and manage.py declared as a script, which is old fashioned but functional. The project ships a benchmarks directory, a pytest.ini, a tox.ini, a runtests.py and a setup.cfg, and it is published on PyPI as dynamic-rest with full documentation at dynamic-rest.readthedocs.org.

Editorial conclusion

Adopt dynamic-rest if your Django REST Framework API needs relationship endpoints, client-controlled include and exclude parameters, or a browsable directory panel, and your consumers can cope with a response format that is not plain DRF. Do not adopt it for a new project without reading the version numbers first: the last push was on 2026-04-13, the newest tagged release is v2.3.0 from 2024-03-26, and the README's stated support for Python 3.6 to 3.8 and Django 2.2 to 3.2 does not match the Python 3.7 to 3.11 classifiers in setup.py. Before you commit, check the DRF version you run against the versions the documentation names, and plan to test the include parameter behaviour against your own serializers rather than trusting the demo.

Frequently asked questions

What is dynamic-rest?

It is an extension for Django REST Framework, published on PyPI as dynamic-rest, that adds linked, sideloaded and embedded relationships, inclusions, exclusions, filtering, sorting and a directory panel. Its classes are designed as drop-in replacements for the standard DRF classes.

How do I install and configure dynamic-rest?

Install it with pip install dynamic-rest, then add rest_framework and dynamic_rest to INSTALLED_APPS in settings.py. If you want the directory panel, replace DRF's browsable API renderer with dynamic_rest.renderers.DynamicBrowsableAPIRenderer in the REST_FRAMEWORK setting.

How does the include[] parameter work in dynamic-rest?

It expresses the requirement to eagerly load, or sideload, relationships, using Django's prefetch_related and select_related semantics. A request such as GET /users/1/?include[]=groups.* returns the user and their groups together instead of only the related IDs.

Which Django and DRF versions does dynamic-rest support?

The README states Python 3.6 to 3.8, Django 2.2, 3.1 and 3.2, and Django REST Framework 3.11 to 3.13, while the setup.py classifiers list Python 3.7 through 3.11. The newest tagged release is v2.3.0 from 2024-03-26 and the last push was on 2026-04-13.

Official sources

  1. AltSchool/dynamic-rest on GitHub
  2. Issues
  3. License: MIT
  4. README
  5. Releases
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.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/altschool-dynamic-rest.svg)](https://hysenlabs.com/projects/altschool-dynamic-rest)

Was this useful?