{"id":3462,"library":"django-ninja","title":"Django Ninja","description":"Django Ninja is a fast, modern web framework for building APIs with Django using Python type hints, Pydantic, and automatic OpenAPI documentation. It aims for high performance and developer friendliness, similar to FastAPI, while leveraging Django's ecosystem. The library maintains a regular release cadence with frequent updates and bug fixes.","status":"active","version":"1.6.2","language":"en","source_language":"en","source_url":"https://github.com/vitalik/django-ninja","tags":["django","rest-api","fastapi-style","pydantic","openapi","api-documentation","type-hints","async"],"install":[{"cmd":"pip install django-ninja","lang":"bash","label":"Install stable version"}],"dependencies":[{"reason":"Core web framework integration.","package":"Django","optional":false},{"reason":"Data validation, serialization, and settings management via type hints.","package":"Pydantic","optional":false}],"imports":[{"symbol":"NinjaAPI","correct":"from ninja import NinjaAPI"},{"symbol":"Router","correct":"from ninja import Router"},{"note":"For `ModelSchema`, `django-ninja` introduced `Meta` for consistency with Django's `ModelForms`. While `Config` is still supported, `Meta` is preferred and more aligned with Pydantic V2's `model_config` concept for custom configurations.","wrong":"class MySchema(ModelSchema):\n    class Config: # Deprecated in Pydantic V2, use ModelSchema.Meta in Django Ninja\n        ...","symbol":"ModelSchema","correct":"from ninja import ModelSchema"},{"symbol":"Query","correct":"from ninja import Query"},{"symbol":"Path","correct":"from ninja import Path"},{"symbol":"Body","correct":"from ninja import Body"},{"symbol":"File","correct":"from ninja import File"},{"symbol":"UploadedFile","correct":"from ninja.files import UploadedFile"}],"quickstart":{"code":"from django.contrib import admin\nfrom django.urls import path\nfrom ninja import NinjaAPI\n\n# In your Django project's main urls.py:\n# from .api import api # Assuming api.py is next to urls.py\n# urlpatterns = [\n#     path('admin/', admin.site.urls),\n#     path('api/', api.urls) # Mount the NinjaAPI\n# ]\n\n# Create an api.py file in your Django project's root directory (next to urls.py)\n# api.py\napi = NinjaAPI(title=\"My Awesome API\", version=\"1.0.0\")\n\n@api.get(\"/hello\")\ndef hello(request):\n    return \"Hello from Django Ninja!\"\n\n@api.get(\"/add\")\ndef add(request, a: int, b: int):\n    return {\"result\": a + b}","lang":"python","description":"This quickstart demonstrates creating a basic API endpoint. Define a `NinjaAPI` instance, then use decorator functions (e.g., `@api.get`) to define API routes. Parameters with type hints are automatically validated and converted. The API instance's `.urls` should be included in your Django project's `urlpatterns`."},"warnings":[{"fix":"Upgrade Pydantic to V2 and refactor Pydantic models according to Pydantic V2 migration guides. Django Ninja's `ModelSchema.Meta` class replaces `BaseModel.Config` for model-based schemas.","message":"Django Ninja v1.0 and later versions require Pydantic V2. Projects upgrading from older Django Ninja versions (0.x) or using Pydantic V1 will encounter breaking changes due to Pydantic's major rewrite.","severity":"breaking","affected_versions":">=1.0.0"},{"fix":"Wrap all blocking (synchronous) ORM calls and other sync I/O operations with `sync_to_async` from `asgiref.sync`. For example: `queryset = await sync_to_async(MyModel.objects.all)()` or `obj = await sync_to_async(MyModel.objects.get)(pk=id)`.","message":"Directly calling Django ORM methods (e.g., `MyModel.objects.all()`) within `async` API views will block the event loop and raise an error. The Django ORM is not fully async-native yet.","severity":"gotcha","affected_versions":"All"},{"fix":"Use the `Status` class explicitly for returning responses with custom HTTP status codes. For example, `return Status(200, {'message': 'Success'})`.","message":"The previous method of returning a tuple `(status_code, body)` to specify HTTP status codes in responses is deprecated.","severity":"deprecated","affected_versions":">=1.6.0"},{"fix":"Review any code that mounts the same `Router` instance multiple times to ensure the new idempotent behavior (where decorators, auth, tags, and throttling are fully isolated between mounts) aligns with expectations. This generally resolves previous errors for such patterns.","message":"As of v1.6.0, routers became idempotent and reusable. While this is an enhancement, it changes behavior around mounting the same router multiple times. Previous workarounds or reliance on non-idempotent behavior might need review.","severity":"breaking","affected_versions":">=1.6.0"},{"fix":"For function-based operations, you might need to manually wrap the Django decorator around the `django-ninja` decorator, or use `router.add_decorator` with a custom universal decorator that handles both sync/async. The `decorate_view` utility or custom middleware might also be necessary for certain scenarios. Refer to the 'Decorators' section of the official documentation.","message":"Standard Django decorators (e.g., `@cache_page`, `@transaction.atomic`) do not directly integrate with Django Ninja operation functions without explicit wrapping.","severity":"gotcha","affected_versions":"All"}],"env_vars":null,"last_verified":"2026-04-11T00:00:00.000Z","next_check":"2026-07-10T00:00:00.000Z"}