Package: django-fastapi-bridge
Django FastAPI BridgeAllows to useFastAPItop ofDjangoRationaleUse 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 applicationAutomatically create documentation and OpenAPI schema with FastAPIBoth 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)TODOInitial ASGI supportWSGI supportAuthentication and authorization bridgeUtils for serialization and updating ORM modelsException handler for DEBUG modeReplacement for most common shortcut / helpersTests and stabilizationQuickstartInstall FastAPI:pip install fastapiInstall required packages:pip install django-fastapi-bridgeAdddjango_fastapitoINSTALLED_APPSin yoursettings.pyfile:INSTALLED_APPS = [
    # ...
    "django_fastapi",
    # ...
]SetASGI_APPLICATIONandWSGI_APPLICATIONin yoursettings.pyfile:ASGI_APPLICATION = "django_fastapi.asgi.application"
WSGI_APPLICATION = "django_fastapi.wsgi.application"Development server (WSGI)Use Django'srunservercommand as usualNotes:ASGI app is wrapped to WSGI interface througha2wsgi.ASGIMiddlewareDjango'srunserverwill not print tracebacks to the stdout and tracebacks aren't generated by FastAPI/Bridge (this should be addressed later)Development server (ASGI w/Daphne)Installdaphne, then adddaphneto theINSTALLED_APPSbeforedjango.core.staticfiles.Run development server:python manage.py runserverProduction server (ASGI w/Uvicorn)Install Uvicorn:pip install uvicornRun uvicorn:DJANGO_SETTINGS_MODULE=yourproject.settings uvicorn django_fastapi.asgi:applicationProduction server (WSGI w/Uvicorn, not recommended)Install Uvicorn:pip install uvicornRun uvicorn:DJANGO_SETTINGS_MODULE=yourproject.settings uvicorn --interface wsgi django_fastapi.wsgi:applicationRunning 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.ConfigurationBase settingsTo configure defaultFastAPIinstance 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)]CORSFASTAPI_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 toTrueFASTAPI_CORS_ALLOW_METHODS: defaults to["*"]FASTAPI_CORS_ALLOW_HEADERS: defaults to["*"]AutodiscoverFASTAPI_AUTODISCOVER: if True, Django FastAPI will automatically
importFASTAPI_AUTODISCOVER_MODULESfrom yourINSTALLED_APPS.
Default:TrueFASTAPI_AUTODISCOVER_MODULES: defaults to["api"]Examples and performanceSeeexample/test_api/api.pyfor more examplesQuerying a database in sync modeWrite your handler as usual:@api.get("/permissions",response_model=PermissionListResource)defpermissions_list():queryset=Permission.objects.all()items=[{"pk":obj.pk,"name":obj.name}forobjinqueryset]returnPermissionListResource(items=items)Querying a database in async modePrepend your function withasynckeyword and query the database in
an async way. BecauseQuerySetis a lazy evaluated object, it will hit
the database during creating list of items. That's why you must useasync forin the list comprehension:@api.get("/async/permissions",response_model=PermissionListResource)asyncdefpermissions_list():queryset=Permission.objects.all()items=[{"pk":obj.pk,"name":obj.name}asyncforobjinqueryset]returnPermissionListResource(items=items)Performance comparisonSync 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: 2200Server command:cd example
DJANGO_SETTINGS_MODULE=fastapi_bridge_test.settings uvicorn django_fastapi.asgi:applicationSoftware versions:Python 3.11.3Django 4.2.5Linux 6.1.49-1-MANJAROImportant notesWith 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 mandatoryrequestargument)Therequestobject used will be FastAPI/Starlette'sRequestobject, not Django oneDjango middlewares can't be used directlyContext processors based on request objects will mostly failAll helpers / shortcut functions based on Django's original request
will not workYour 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 worksThis 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 withasync_to_syncorsync_to_asyncfromasgiref.syncmodule.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 raiseSynchronousOnlyOperationexception. 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/AlternativesDjango Ninja- REST framework for Django inspired by FastAPILicenseISCCopyright 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.