Django Ninja Extra
Django Ninja Extra is a powerful extension for Django Ninja, providing class-based utilities and advanced features for building REST APIs. It augments Django Ninja with API controllers, an advanced permission system (similar to Django REST Framework), dependency injection, and a service layer for business logic. The library is actively maintained, with its current version being 0.31.4, and follows a frequent release cadence to support the latest Django and Django Ninja versions.
Common errors
-
TypeError: Cannot create a consistent method resolution order (MRO) for bases PaginatedResponseSchema, Generic
cause Incompatible inheritance hierarchy, often due to a specific interaction between django-ninja-extra's PaginatedResponseSchema and certain Pydantic versions.fixThis specific MRO issue was largely addressed with the Pydantic v2 migration in `django-ninja-extra>=0.30.9`. Ensure you are on the latest compatible versions of `django-ninja-extra` and `pydantic`. If on an older `django-ninja-extra` version, try pinning `pydantic` to `pydantic<2.0,>=1.10.0`. -
HTTP 405 Method Not Allowed
cause Attempting an HTTP method (e.g., POST) on a controller route that only has a decorator for a different method (e.g., `@http_get`).fixEnsure the controller method is decorated with the correct HTTP verb decorator for the request you are making (e.g., `@http_post`, `@http_put`, `@http_delete`). -
AttributeError: 'NinjaExtraAPI' object has no attribute 'register_controller'
cause Misspelling the method to register controllers or attempting to register a controller with a standard `NinjaAPI` instance.fixEnsure you are using `NinjaExtraAPI()` and call `api.register_controllers(YourControllerClass)`. Note the plural `controllers`. -
pydantic.error_wrappers.ValidationError: 1 validation error for YourSchema
cause Input data for a request body or query parameters does not conform to the Pydantic schema defined for the endpoint.fixReview the API endpoint's expected schema and ensure the incoming request data matches the types, required fields, and constraints defined in your Pydantic model. Check for missing required fields or incorrect data types. -
ModuleNotFoundError: No module named 'ninja_extra.controllers'
cause Attempting to import a symbol from an incorrect or deprecated path within `django-ninja-extra`.fixAlways refer to the official documentation for current import paths. Many core components are directly available from `ninja_extra` (e.g., `from ninja_extra import api_controller`) rather than deeper submodules like `ninja_extra.controllers`.
Warnings
- breaking Version 0.30.9 introduced a migration from Pydantic v1 config to Pydantic v2 config. This is a significant breaking change if your project relies on Pydantic v1 specific syntax or behaviors.
- deprecated The `get_api_controller()` method has been deprecated and replaced by the `api_controller` property for accessing controller instances within the API.
- breaking In versions prior to 0.22.2, the `service` attribute in `ModelController` was expected to be a class object. It was changed to an instance object, requiring `service_type` to be specified.
- gotcha Prior to versions 0.31.3/0.31.4, there were issues with API-level authentication and throttling not correctly inheriting to controller routes.
- gotcha An MRO (Method Resolution Order) bug might occur with `PaginatedResponseSchema` when using `django-ninja-extra>=0.21` in combination with specific Pydantic versions, causing `TypeError: Cannot create a consistent method resolution order (MRO)`.
Install
-
pip install django-ninja-extra
Imports
- NinjaExtraAPI
from ninja import NinjaAPI
from ninja_extra import NinjaExtraAPI
- api_controller
from ninja_extra import api_controller
- http_get
from ninja_extra import http_get
- ModelControllerBase
from ninja_extra import ModelControllerBase
- ModelService
from ninja_extra import ModelService
Quickstart
import os
from django.conf import settings
from django.urls import path
from ninja_extra import NinjaExtraAPI, api_controller, http_get
if not settings.configured:
settings.configure(
DEBUG=True,
INSTALLED_APPS=[
'django.contrib.auth',
'django.contrib.contenttypes',
'ninja_extra',
],
ROOT_URLCONF=__name__,
SECRET_KEY='a-very-secret-key',
TEMPLATES=[{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'APP_DIRS': True,
}],
)
api = NinjaExtraAPI()
@api_controller("/items", tags=["Items"])
class ItemController:
@http_get("/")
def list_items(self):
return [{"id": 1, "name": "Item 1"}, {"id": 2, "name": "Item 2"}]
@http_get("/{item_id}")
def get_item(self, item_id: int):
return {"id": item_id, "name": f"Item {item_id}"}
api.register_controllers(ItemController)
urlpatterns = [
path("api/", api.urls),
]
# To run this in a Django project, you'd integrate `api.urls` into your project's `urls.py`:
# from django.urls import path, include
# from .api import api # Assuming your api setup is in api.py
# urlpatterns = [
# path("api/", api.urls),
# ]
# Remember to add 'ninja_extra' to your INSTALLED_APPS in settings.py