django-hatchway (an API framework inspired by the likes of FastAPI, but while trying to keep API views as much like standard Django views as possible)

Announce on mastodon

It’s been running great inside Takahē for over a week, so I have extracted Hatchway, my new Django API framework, into its own project: https://github.com/andrewgodwin/django-hatchway

In short - it uses type annotations for everything, and it uses standard URL patterns, as these were the things that I couldn’t find elsewhere.

Description

Hatchway is an API framework inspired by the likes of FastAPI, but while trying to keep API views as much like standard Django views as possible.

It was built for, and extracted from, Takahē; if you want to see an example of it being used, browse its api app.

Installation

Install Hatchway from PyPI:

pip install django-hatchway

And add it to your INSTALLED_APPS:

INSTALLED_APPS = [
    ...
    "hatchway",
]

Usage

To make a view an API endpoint, you should write a standard function-based view, and decorate it with @api_view.get, @api_view.post or similar:

from hatchway import api_view

@api_view.get
def my_api_endpoint(id: int, limit: int = 100) -> list[str]:
    ...

The types of your function arguments matter; Hatchway will use them to work out where to get their values from and how to parse them.

All the standard Python types are supported, plus Pydantic-style models (which ideally you should build based on the hatchway.Schema base class, as it understands how to load things from Django model instances).

Your return type also matters - this is what Hatchway uses to work out how to format/validate the return value.

You can leave it off, or set it to Any, if you don’t want any return validation.

URL Patterns

You add API views in your urls.py file like any other view

urlpatterns = [
    ...
    path("api/test/", my_api_endpoint),
]

The view will only accept the method it was decorated with (e.g. GET for api_view.get).

If you want to have two or more views on the same URL but responding to different methods, use Hatchway’s methods object:

from hatchway import methods

urlpatterns = [
    ...
    path(
        "api/post/<id>/",
        methods(
            get=posts.post_get,
            delete=posts.posts_delete,
        ),
    ),
]