Skip to content

Proposal to add before_endpoint and after_endpoint hooks for dependency injection #1601

@Ben-Sylvester

Description

@Ben-Sylvester

Hello

I do like to propose a small and optional feature that will enable clean dependency injection and request-scoped context in Django Ninja, without breaking any existing behaviour.

Motivation
A lot of real-world APIs need a simple way to handle state that’s specific to each request. Think about stuff like the authenticated user, trace IDs, multi-tenant info, service instances, metadata for logging, or even just a cache that sticks around for the life of the request.

Right now, dealing with this is kind of a mess. People use middleware tricks or write custom decorators, and every codebase does it differently. An official, lightweight hook system would make dependency injection way cleaner and easier to follow.

Proposed API (fully optional)

Add two optional parameters to NinjaAPI:

api = NinjaAPI(
    before_endpoint=build_context,
    after_endpoint=log_or_cleanup,
)

Where:

before_endpoint(request) returns a context object

after_endpoint(request, response) post-processing

The context (ctx) is automatically injected into endpoint handlers if they include a ctx parameter:

@api.get("/items")
def list_items(request, ctx):
    return {"user": ctx["user"], "trace": ctx["trace_id"]}

Endpoints not using ctx remain unchanged, 100% backward compatible

Implementation process is minimal

# ninja/operation.py
def run(self, request, *args, **kwargs):
    ctx = None
    if self.api.before_endpoint:
        ctx = self.api.before_endpoint(request)

    if ctx is not None and "ctx" in self.signature.parameters:
        kwargs["ctx"] = ctx

    result = self.view_func(request, *args, **kwargs)

    if self.api.after_endpoint:
        result = self.api.after_endpoint(request, result)

    return result

The Benefits are:

  • Enables clean dependency injection
  • Makes request-scoped context trivial
  • Great for logging, tracing, metrics, multi-tenancy
  • Optional and backward compatible
  • Zero breaking changes
  • Very small patch
  • Easier large-scale project structure

Willingness to contribute
If the maintainers approve this direction, I am happy to submit a pull request with the implementation.
The patch is small (40 lines), fully backward compatible, and easy to review.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions