Build FastAPI app top of Django
Project description
Django FastAPI Bridge
Allows to use FastAPI top of Django
Rationale
- Use Django as a core for your app logic, admin panel and multiple addons available for years ("batteries included"), then create a web interface with FastAPI ("batteries also included")
- Add a web interface built with FastAPI to your existing Django project, until you migrate it to fully ASGI compatible application
- Automatically create documentation and OpenAPI schema with FastAPI
- Both Django and FastAPI are mature, stable, supported and well known products with large communities. No need to use other tools nor rely on less or more similar clones.
- Eventually run the same Django project in full ASGI mode to enable async features like long-polling (although you must carefully prepare your project for such cases)
TODO
- Initial ASGI support
- WSGI support
- Authentication and authorization bridge
- Utils for serialization and updating ORM models
- Exception handler for DEBUG mode
- Replacement for most common shortcut / helpers
- Tests and stabilization
Quickstart
Install FastAPI:
pip install fastapi
Install required packages:
pip install django-fastapi-bridge
Add django_fastapi
to INSTALLED_APPS
in your settings.py
file:
INSTALLED_APPS = [
# ...
"django_fastapi",
# ...
]
Set ASGI_APPLICATION
and WSGI_APPLICATION
in your settings.py
file:
ASGI_APPLICATION = "django_fastapi.asgi.application"
WSGI_APPLICATION = "django_fastapi.wsgi.application"
Development server (WSGI)
Use Django's runserver
command as usual
Notes:
- ASGI app is wrapped to WSGI interface through
a2wsgi.ASGIMiddleware
- Django's
runserver
will not print tracebacks to the stdout and tracebacks aren't generated by FastAPI/Bridge (this should be addressed later)
Development server (ASGI w/Daphne)
Install daphne
, then add daphne
to the INSTALLED_APPS
before
django.core.staticfiles
.
Run development server:
python manage.py runserver
Production server (ASGI w/Uvicorn)
Install Uvicorn:
pip install uvicorn
Run uvicorn:
DJANGO_SETTINGS_MODULE=yourproject.settings uvicorn django_fastapi.asgi:application
Production server (WSGI w/Uvicorn, not recommended)
Install Uvicorn:
pip install uvicorn
Run uvicorn:
DJANGO_SETTINGS_MODULE=yourproject.settings uvicorn --interface wsgi django_fastapi.wsgi:application
Running the application in WSGI mode will be safest than in ASGI mode, which relies on protections built into Django, but the overall performance can be more than twice as low.
Configuration
Base settings
To configure default FastAPI
instance you can use these settings:
FASTAPI_TITLE
: set's API title [FastAPI(title=FASTAPI_TITLE)
]FASTAPI_VERSION
: set's API version [FastAPI(version=FASTAPI_VERSION)
]FASTAPI_ROOT_PATH
: set's API root path [FastAPI(root_path=FASTAPI_ROOT_PATH)
]
CORS
FASTAPI_CORS_ENABLED
: if True, adds CORS middleware to the default FastAPI instance (disabled by default)FASTAPI_CORS_ALLOW_ORIGINS
: defaults to["*"]
FASTAPI_CORS_ALLOW_CREDENTIALS
: defaults toTrue
FASTAPI_CORS_ALLOW_METHODS
: defaults to["*"]
FASTAPI_CORS_ALLOW_HEADERS
: defaults to["*"]
Autodiscover
FASTAPI_AUTODISCOVER
: if True, Django FastAPI will automatically importFASTAPI_AUTODISCOVER_MODULES
from yourINSTALLED_APPS
. Default:True
FASTAPI_AUTODISCOVER_MODULES
: defaults to["api"]
Examples and performance
See example/test_api/api.py for more examples
Querying a database in sync mode
Write your handler as usual:
@api.get("/permissions", response_model=PermissionListResource)
def permissions_list():
queryset = Permission.objects.all()
items = [{"pk": obj.pk, "name": obj.name} for obj in queryset]
return PermissionListResource(items=items)
Querying a database in async mode
Prepend your function with async
keyword and query the database in
an async way. Because QuerySet
is a lazy evaluated object, it will hit
the database during creating list of items. That's why you must use
async for
in the list comprehension:
@api.get("/async/permissions", response_model=PermissionListResource)
async def permissions_list():
queryset = Permission.objects.all()
items = [{"pk": obj.pk, "name": obj.name} async for obj in queryset]
return PermissionListResource(items=items)
Performance comparison
Sync mode:
Concurrency Level: 10
Time taken for tests: 15.217 seconds
Complete requests: 10000
Failed requests: 0
Requests per second: 657.16 [#/sec] (mean)
Time per request: 15.217 [ms] (mean)
Async mode:
Concurrency Level: 10
Time taken for tests: 6.374 seconds
Complete requests: 10000
Failed requests: 0
Requests per second: 1568.97 [#/sec] (mean)
Testing platform:
Machine:
Type: Desktop Mobo: Micro-Star model: B550-A PRO (MS-7C56) v: 2.0
Memory:
System RAM: total: 32 GiB available: 31.27 GiB used: 9.44 GiB (30.2%)
CPU:
Info: 12-core model: AMD Ryzen 9 5900X bits: 64 type: MT MCP cache:
L2: 6 MiB
Speed (MHz): avg: 2425 min/max: 2200/4950 cores: 1: 3598 2: 2869 3: 2874
4: 2200 5: 2819 6: 2200 7: 2200 8: 2200 9: 2200 10: 2200 11: 2199 12: 2199
13: 3584 14: 2200 15: 2879 16: 2200 17: 2200 18: 2200 19: 2200 20: 2200
21: 2200 22: 2200 23: 2200 24: 2200
Server command:
cd example
DJANGO_SETTINGS_MODULE=fastapi_bridge_test.settings uvicorn django_fastapi.asgi:application
Software versions:
- Python 3.11.3
- Django 4.2.5
- Linux 6.1.49-1-MANJARO
Important notes
With the bridge a typical Django's server stack (middlewares, requests, responses) will not be used. This causes some incompatibilities, but in a this should not be an issue while building HTTP APIs top of Django:
- The interface of FastAPI callbacks will never be
same as Django's views interface (i.e. no mandatory
request
argument) - The
request
object used will be FastAPI/Starlette'sRequest
object, not Django one - Django middlewares can't be used directly
- Context processors based on request objects will mostly fail
- All helpers / shortcut functions based on Django's original request will not work
- Your application can run in synchronous mode with a potential performance cost, until you use fully async code (see "Why this works" notes below). NB: This is similar how all alternatives based on ASGI protocol works.
Why this works
This bridge disables Django's HTTP server and uses FastAPI/Starlette directly.
At this moment Django has partial but stable support for the asynchonous mode,
and for a compatibility reasons it can switch between sync and asynchronous mode
automatically. In cases where you are mixing sync and async calls, you must
wrap them with async_to_sync
or sync_to_async
from asgiref.sync
module.
Current versions of Django (4.1+) handles unsafe non-async calls very nicely, so
there are no errors known from the past. Django's async-unsafe parts are protected
from execution in async environment and will raise SynchronousOnlyOperation
exception. In case of third party apps/addons you must make sure they're async-safe
or protected.
Please note that switching between sync and async modes comes at a cost. Although Django tries to optimize the number of context switches, in some configurations there may be more than one, which may result in a performance penalty.
More details can be found in the Django documentation: https://docs.djangoproject.com/en/4.2/topics/async/
Alternatives
- Django Ninja - REST framework for Django inspired by FastAPI
License
ISC
Copyright 2023 Marcin Nowak <marcin.j.nowak.gmail.com>
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED “AS IS” AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
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
File details
Details for the file django-fastapi-bridge-0.2.tar.gz
.
File metadata
- Download URL: django-fastapi-bridge-0.2.tar.gz
- Upload date:
- Size: 10.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.2 CPython/3.11.3
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 21c82c68c557f0c986383889429e01ee105ed98a452e73dce4c0bda2e446d0b2 |
|
MD5 | 5a3a456bb071ab70eb006ff6fdb7aa4f |
|
BLAKE2b-256 | b23ef7276e848bbd4bd745e63cee30feba0911d25e15ccdaf15cf78539128d50 |
File details
Details for the file django_fastapi_bridge-0.2-py3-none-any.whl
.
File metadata
- Download URL: django_fastapi_bridge-0.2-py3-none-any.whl
- Upload date:
- Size: 9.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.2 CPython/3.11.3
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | bdd5ae651cc1164ec42d00ed8f859e662977ce6666e68ced5bd5c7298840f32a |
|
MD5 | de5d882f9beb2ee917e54afb30ebb5c7 |
|
BLAKE2b-256 | f5b28019d7def8446a460ab381fc38e7948758e74f9daa8f58edc73469506425 |