Good day! Please tell me how you can solve the following task in Python + FastAPI.
There is a test project:
app / main.py - main file
app / routes / users.py -set of api methods
app / repos / factory.py - repository factory
app / repos / user_repository.py - repositories
app / handlers / factory.py - handler factory
app / handlers / users.py - handlers
app / domain / user.py - data class
The main and routes structure is the same as in the example https://fastapi.tiangolo.com/tutorial/bigger-applications/
In the routes/users.py file:
from fastapi import APIRouter, Depends
from ..handlers import factory
router = APIRouter()
@router.get("/users/", tags=["users"])
def read_users(handler=Depends(factory.get_handler)):
return handler.get_all()
In the handlers/factory.py:
from fastapi import Depends
from .users import UserHandler1
def get_handler(handler=Depends(UserHandler1)):
return handler
In the handlers/users.py:
from fastapi import Depends
from ..repos import factory
class UserHandler1:
def __init__(self):
pass
def get_all(self, repo=Depends(factory.get_repo)):
return repo.get_all()
repos/factory.py:
from fastapi import Depends
from ..repos.user_repository import UserRepository
def get_repo(repo=Depends(UserRepository)):
return repo
repos/user_repository.py:
from ..domain.user import User
class UserRepository:
def __init__(self):
pass
def get_all(self):
return [User(1, 'A'), User(2, 'B'), User(3, 'C')]
domain/user.py:
class User:
id: int
name: str
def __init__(self, id, name):
self.id = id
self.name = name
Run hypercorn: app.main:app --reload
Call api method: http://127.0.0.1:8000/users/
And get the error AttributeError: 'Depends' object has no attribute 'get_all'
If you remove the level of handlers and do this, then everything will work.
routes/users.py:
from fastapi import APIRouter, Depends
from ..repos import factory
router = APIRouter()
@router.get("/users/", tags=["users"])
def read_users(repo=Depends(factory.get_repo)):
return repo.get_all()
It also works if you completely remove all Depends and create
UserRepository and UserHandler1 directly in factories.
QUESTION: How do I use Depends in this case and why doesn't it work?
I attach an archive with a test project
test.zip
UserHandler1 is not a callable. You need to implement __call__ there. Depends expects a callable.
@Kludex that's not correct - classes are callable, they return an instance when called.
@dmpyatin here's one way of fixing your issue:
class UserHandler1:
def __init__(self, repo=Depends(get_repo)):
self.repo = repo
def get_all(self):
return self.repo.get_all()
the reason this is required is because you are calling UserHandler1.get_all() directly, so the repo=Depends(get_repo) is never resolved.
You're right. What I said doesn't make any sense. 馃馃憤
@Mause, Many thanks! Your example helped a lot
Feel free to close the issue if that solves it :)
Most helpful comment
@Kludex that's not correct - classes are callable, they return an instance when called.
@dmpyatin here's one way of fixing your issue:
the reason this is required is because you are calling
UserHandler1.get_all()directly, so therepo=Depends(get_repo)is never resolved.