Rapidly generate CRUD API endpoints for your Django models with Django Ninja. Includes dynamic schema generation and customizable hooks.
Project description
Lazy Ninja 🥷
Lazy Ninja is a Django library that automates the generation of CRUD API endpoints using Django Ninja. It dynamically scans your Django models and creates Pydantic schemas for listing, detailing, creating, and updating records—all while allowing you to customize behavior via hook functions (controllers) and schema configurations.
By leveraging Django Ninja, Lazy Ninja benefits from automatic, interactive API documentation generated through OpenAPI, giving developers an intuitive interface to quickly visualize and interact with API endpoints.
Important Note: This pre-release (alpha) version only supports JSON data.
multipart/form-data(file uploads) is not supported. ForImageField/FileFieldfields, store the full URL as a string. See the Roadmap for future plans.
Table of Contents
Installation
Install Lazy Ninja via pip:
pip install lazy-ninja
Installing from source
If you prefer to work with the latest code or contribute to the project, you can clone the repository and install it in editable mode:
git clone https://github.com/AghastyGD/lazy-ninja.git
cd lazy-ninja
pip install -e .
Running Tests
To run the test suite, make sure to install the development dependencies:
pip install -r requirements.txt
Then run:
pytest
Quick Start
Here’s a simple example of integrating Lazy Ninja into your Django project to automatically generate CRUD endpoints:
# django_project/core/api.py
from ninja import NinjaAPI
from lazy_ninja.builder import DynamicAPI
api = NinjaAPI()
# Initialize the DynamicAPI instance
dynamic_api = DynamicAPI(api)
# Automatically register routes for all Django models.
dynamic_api.register_all_models()
# Include api.urls in your project's urls.py
You can also customize schema generation and specify excluded apps:
from ninja import NinjaAPI
from lazy_ninja.builder import DynamicAPI
api = NinjaAPI()
# Optional: Schema configuration for models (e.g., excluding fields or marking fields as optional)
schema_config = {
"Genre": {"optional_fields": ["slug"], "exclude": ["id"]}, # "id" excluded from create/update by default
}
# Custom schemas for specific models
custom_schemas = {
"Tag": {
"list": TagListSchema,
"detail": TagDetailSchema,
"create": TagCreateSchema,
"update": TagUpdateSchema,
}
}
# Instantiate DynamicAPI with your custom settings.
# By default, the following apps are excluded: {"auth", "contenttypes", "admin", "sessions"}.
# To generate endpoints for these apps, pass an empty set.
dynamic_api = DynamicAPI(
api,
schema_config=schema_config,
custom_schemas=custom_schemas,
excluded_apps={"auth", "contenttypes", "admin", "sessions"}
)
dynamic_api.register_all_models()
Features
-
Automatic CRUD endpoints:
Scans all installed Django models (excluding specified apps) and automatically registers CRUD routes using Django Ninja. -
Dynamic schema generation:
Uses Pydantic (via Django Ninja) to generate schemas for listing, detailing, creating, and updating models, with options to exclude or mark fields as optional. -
Custom controllers (Hooks):
Override default behavior by registering custom controllers via the Model Registry. Available hooks include:- before_create: Modify the creation payload.
- after_create: Post-process after record creation.
- before_update / after_update: Adjust data during updates.
- before_delete / after_delete: Handle pre- and post-deletion logic.
- custom_response: Customize the API response.
Usage
Automatic route generation
For example, a model named Book will have endpoints like:
GET /book/for listingGET /book/{id}for detailPOST /book/for creationPATCH /book/{id}for updateDELETE /book/{id}for deletion
Customizing schemas
-
Schema config:
Provide a dictionary mapping model names to configuration settings. For example:schema_config = { "Book": {"optional_fields": ["description"], "exclude": ["id"]}, }
-
Custom schemas:
Provide your own Pydantic schema classes for specific operations:custom_schemas = { "Book": { "list": BookListSchema, "detail": BookDetailSchema, "create": BookCreateSchema, "update": BookUpdateSchema, } }
Controller hooks
As we see above, Lazy Ninja allows you to register custom controllers that override the default behavior. A custom controller can modify the payload before creating or updating an object, or perform actions after deletion.
To use custom controllers:
-
Organize your controllers:
Create acontrollersdirectory (with an__init__.py) in your Django app and add your controller files (e.g.,book.py,genre.py). -
Register controllers (New Method):
In your controller file (e.g.,book.py), define and register a controller:# django_project/core/controllers/book.py from django.utils.text import slugify from lazy_ninja import BaseModelController, controller_for @controller_for("Book") class BookController(BaseModelController): @classmethod def before_create(cls, request, payload, create_schema): """ Hook executed before creating a new Book. It validates the 'title' field against forbidden words, converts it to lowercase, and automatically generates a slug. """ forbidden_words = ["forbidden", "banned", "test"] payload_data = payload.model_dump() for word in forbidden_words: if word in payload_data['title'].lower(): raise ValueError(f"Invalid title: contains forbidden word '{word}'") payload_data['title'] = payload_data['title'].lower() payload_data['slug'] = slugify(payload_data['title']) return create_schema(**payload_data) @classmethod def before_update(cls, request, instance, payload, update_schema): """ Hook executed before updating an existing Book. If the 'title' field is updated, it automatically updates the slug. """ payload_data = payload.model_dump() if 'title' in payload_data: payload_data['slug'] = slugify(payload_data['title']) return update_schema(**payload_data)
Configuration options
-
excluded_apps:
Lazy Ninja automatically skips models from apps likeauth,contenttypes,admin, andsessions. You can override this by passing your own set of apps when initializing DynamicAPI. -
schema_config:
Define which fields to exclude or mark as optional for each model. -
custom_schemas:
Provide custom Pydantic schemas for list, detail, create, and update operations for specific models.
Roadmap
- Basic CRUD operations: Support for listing, retrieving, creating, updating, and deleting objects for Django models (JSON only).
- File upload:
- Support for
multipart/form-datauploads. - Configurable automatic handling of
ImageFieldandFileField. - Option for custom upload handling via hooks.
- Support single and multiple files fields.
- Support for
- Asynchronous operations:
- Make all CRUD operations asynchronous by default (using Django's async ORM).
- Provide an option to use synchronous operations.
- Authentication and RBAC:
- Planned integration of token-based authentication.
- Role-based access control to protect automatically generated routes.
- Centralized schema and security config:
- Future versions may allow combining schema customization and security settings into a single configuration object.
- Advanced model relationships:
- Improved handling of relationships (foreign keys, many-to-many).
- Support for nested schemas.
- Filtering and sorting:
- Built-in support for filtering and sorting list results based on query parameters.
- Pagination:
- Configurable pagination for list results.
- Customizable endpoints:
- Allow to add custom extra endpoints.
- API versioning:
- Built-in support for API versioning.
License
This project is licensed under the MIT License.
See the LICENSE file for details and full license text.
Contact
Augusto Domingos
www.augustodomingos.dev
Project link: https://github.com/AghastyGD/lazy-ninja
Feel free to reach out for questions, suggestions, or contributions ❤️.
Project details
Release history Release notifications | RSS feed
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
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file lazy_ninja-0.5.0.tar.gz.
File metadata
- Download URL: lazy_ninja-0.5.0.tar.gz
- Upload date:
- Size: 24.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3b15205eb7e2f03969ff5f3881ed4ea7b039a9b54206866c90b610f0537c69ce
|
|
| MD5 |
63278c834a97c84f9a379fe51015e83e
|
|
| BLAKE2b-256 |
d964cc9f8b731804ceee2244d1e54e2737f5e71def7803a9b59580187a10bb76
|
Provenance
The following attestation bundles were made for lazy_ninja-0.5.0.tar.gz:
Publisher:
python-publish.yml on AghastyGD/lazy-ninja
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
lazy_ninja-0.5.0.tar.gz -
Subject digest:
3b15205eb7e2f03969ff5f3881ed4ea7b039a9b54206866c90b610f0537c69ce - Sigstore transparency entry: 186676587
- Sigstore integration time:
-
Permalink:
AghastyGD/lazy-ninja@b62061353f28529002864b6f6bfc48fcf19aaa95 -
Branch / Tag:
refs/tags/v0.5.0 - Owner: https://github.com/AghastyGD
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@b62061353f28529002864b6f6bfc48fcf19aaa95 -
Trigger Event:
release
-
Statement type:
File details
Details for the file lazy_ninja-0.5.0-py3-none-any.whl.
File metadata
- Download URL: lazy_ninja-0.5.0-py3-none-any.whl
- Upload date:
- Size: 19.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d614da13910fba007962b66a456d339c8eaed6054bf916d88019f879c26ff851
|
|
| MD5 |
c4fd7b843ff59b4a8131aa4e1213a88e
|
|
| BLAKE2b-256 |
e15f51dc4b6facbaf0b32c7501eb4ce1060c5b3def107400586ca47f830be0ad
|
Provenance
The following attestation bundles were made for lazy_ninja-0.5.0-py3-none-any.whl:
Publisher:
python-publish.yml on AghastyGD/lazy-ninja
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
lazy_ninja-0.5.0-py3-none-any.whl -
Subject digest:
d614da13910fba007962b66a456d339c8eaed6054bf916d88019f879c26ff851 - Sigstore transparency entry: 186676591
- Sigstore integration time:
-
Permalink:
AghastyGD/lazy-ninja@b62061353f28529002864b6f6bfc48fcf19aaa95 -
Branch / Tag:
refs/tags/v0.5.0 - Owner: https://github.com/AghastyGD
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@b62061353f28529002864b6f6bfc48fcf19aaa95 -
Trigger Event:
release
-
Statement type: