Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dependency Injection support with anydi #1155

Open
antonrh opened this issue May 8, 2024 · 0 comments
Open

Dependency Injection support with anydi #1155

antonrh opened this issue May 8, 2024 · 0 comments

Comments

@antonrh
Copy link
Contributor

antonrh commented May 8, 2024

As the author of the anydi library, which has been primarily used with FastAPI, I've decided to use Django Ninja for my next project and integrate it with anydi. I want to share how to use them in combination and point out some implementation details which might seem a bit 'patchy'.

https://anydi.readthedocs.io/en/stable/extensions/django/

Here is a quick guide on how to set this up:

First, install the anydi library:

pip install anydi

Add anydi.ext.django to the bottom of your INSTALLED_APPS in settings.py:

INSTALLED_APPS = [
    ...
    'anydi.ext.django',
]

Configure the ANYDI settings in settings.py:

ANYDI = {
    "PATCH_NINJA": True,
}

This setting patches Django Ninja to use anydi for dependency injection. The implementation involves replacing the Operation and AsyncOperation classes with custom ones that resolve dependencies using anydi. The details of this can be found here: anydi integration for Django Ninja. I welcome any advice on how to improve this.

Assume you have a service that you want to inject:

class UserService:
    def create_user(self, email: str, password: str) -> User:
        # Business logic can be much more complex ;)
        return User.objects.create_user(email=email, password=password)

You can now inject the service directly into your endpoint:

import anydi
from django.http import HttpRequest
from ninja import Router

from myapp.users.services import UserService


api = Router()


@api.post("/users")
def create_user(
    request: HttpRequest,
    input_data: CreateUserInput,
    user_service: UserService = anydi.auto
) -> Any:
    return user_service.create_user(
        email=input_data.email,
        password=input_data.password,
    )

Using modules

myapp/users/module.py

import anydi

from myapp.users.repositories import UserRepository
from myapp.users.services import UserService


class UsersModule(anydi.Module):
    @anydi.provider(scope="singleton")
    def user_repository(self) -> UserRepository:
        return UserRepository()

    @anydi.provider(scope="singleton")
    def user_service(self, user_repository: UserRepository) -> UserService:
        return UserService(user_repository=user_repository)

Register UsersModule in settings.py

ANYDI = {
    "PATCH_NINJA": True,
    "MODULES": [
        "myapp.users.module.UsersModule"
    ]
}

You can also use all the features of anydi with Django Ninja, including scopes, named dependencies, modules, async support, etc.

For more details, please check out the anydi documentation: anydi Documentation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant