I'm dynamically creating endpoints in in a FastAPI project based on models loaded from another file. When I loop over these I expected to be able to get the value of the variable in the loop inside the async function. However I get only the last value the variable held. This will probably be more clear with code:
my_models = [
("FooModel", FooModel),
("BarModel", BarModel),
]
app = FastAPI()
for name, model in my_models:
snake_name = utils.camel_to_snake(name)
title_name = utils.camel_to_title(name)
@app.post(
f"/{snake_name}",
response_model=model,
name=f"{title_name} Create",
)
async def validate_item(item: model, request: Request):
logger.info(
f"[Valid] {request.method} {title_name} ID: {item.identifier()}"
)
return item
The FastAPI endpoints get created correctly, but wether I hit the /foo_model
endpoint or the /bar_model
endpoint the logger will print "Bar Model" for title_name
. I expected the async def to act like a closure with a temporary local scope which holds what was in the outer variable when defined. It seems like it is actually waiting to evaluate it until the time it is called and it holds whatever was the last in the for loop.
The values are what I expect inside the @app.post
decorator but not inside the validate_item
itself.
How can I get title_name
to behave like how I want and have it hold the proper value when defining it? Also does model
in the signature behave the same way?
I'm using:
- Python 3.10.12
- fastapi 0.95.1
- and running it using a UvicornWorker
- uvicorn 0.21.1