wwaldner
wwaldner

Reputation: 73

Configuration/Dependency using multiple file application in FastAPI

I am trying to figure out how to make configuration/singleton available to different module. Perhaps there is a standard Python way of doing this that I don't know yet. So I create a configuration singleton that has all the app configurations and want to 'share' this with all modules. Same use-case would apply to sharing DB connection.

main.py

app = FastApi()
config = some_config_object_from_somewhere()

app.include_router(
        collection.router,
        prefix='/api/collection'
    )

api/collection.py

router = APIRouter()
@router.post("/", status_code=201)
async def collect():
    # I want to use config that is created/defined in main.py
    # HOW?  I thought dependency injection that is built into FastAPI would
    # help, but can't seem to define something in a different module and have it
    # available in the 'router' module

Upvotes: 4

Views: 8659

Answers (2)

jrc
jrc

Reputation: 21929

According to @tiangolo (the creator of FastAPI):

"You can declare the same dependency at the router or decorator level and then declare it again in the path operation to get its value.

It won't be evaluated twice, it doesn't add any extra computation, there's a dependency cache in place that stores the values of already solved dependencies for a given request

https://github.com/tiangolo/fastapi/issues/424#issuecomment-584169213

So for the case of sharing a DB connection, you would simply need to re-import get_db and re-declare it in the router file.

For the case of sharing configuration data, however, the FastAPI documentation states that dependencies are for "shared logic", sharing "database connections", and enforcing "security, authentication, role requirements"—which seems different than shared data.

Putting your configuration data into its own module does the job (doesn't need to be implemented as a singleton) and is officially Pythonic:

The canonical way to share information across modules within a single program is to create a special module (often called config or cfg). Just import the config module in all modules of your application; the module then becomes available as a global name. Because there is only one instance of each module, any changes made to the module object get reflected everywhere.

https://docs.python.org/3/faq/programming.html#how-do-i-share-global-variables-across-modules

(The Singleton pattern is arguably less Pythonic.)

Upvotes: 2

tuned
tuned

Reputation: 1125

In general, about project structure, the basic structure of a FastAPI application is the the same as a Flask one, see here:

It’s time to start coding! Create the flaskr directory and add the __init__.py file. The __init__.py serves double duty: it will contain the application factory, and it tells Python that the flaskr directory should be treated as a package

FastAPI (and also Flask and other functional-style framework) defines database access in terms of functions using sessions, see here.

Below on that documentation page:

# Dependency
def get_db():
    try:
        db = SessionLocal()
        yield db
    finally:
        db.close()


@app.post("/users/", response_model=schemas.User)
def create_user(user: schemas.UserCreate, db: Session = Depends(get_db)):  # <<< injected here
    db_user = crud.get_user_by_email(db, email=user.email)
    if db_user:
        raise HTTPException(status_code=400, detail="Email already registered")
    return crud.create_user(db=db, user=user)

Upvotes: 2

Related Questions