problems with mixing dependency with new query params #13448
Replies: 5 comments 12 replies
-
|
Hi @michelkluger, For instance, take a look at this bug issue #11037 (comment) |
Beta Was this translation helpful? Give feedback.
-
|
@michelkluger: it seems that everything was interpreted as query parameters. 😃 Probably, one has to choose either to use the query parameters or Query Parameter model. If this is the case, then it would make sense to mention this in the docs. This issue might be related: #13447 I'm adding the code, that reproduces your results: from fastapi import FastAPI, Query, Depends
from pydantic import BaseModel, Field
app = FastAPI()
class Release:
def __init__(self, version, flavour):
self.version = version
self.flavour = flavour
def get_release(version="premium", flavour="latest"):
return Release(version, flavour)
class FilterParams(BaseModel):
limit: int = Field(100, gt=0, le=100)
offset: int = Field(0, ge=0)
order_by: Literal["created_at", "updated_at"] = "created_at"
tags: list[str] = []
@app.get("/items/")
async def read_items(
release: Annotated[Release, Depends(get_release)],
filter_query: Annotated[FilterParams, Query()]
):
return filter_query |
Beta Was this translation helpful? Give feedback.
-
|
actually it turns out that they can be mixed using a MixIn pattern 😃 from fastapi import FastAPI, Query
from pydantic import BaseModel, Field
from typing import Annotated
app = FastAPI()
class ReleaseFilter:
version: str = Field(default="latest", examples=["latest", "unstable", "deprecated"])
flavour: str = Field(default="silver", examples=["silver", "gold", "platinum"])
class PageParams:
limit: int = Field(default=25, examples=[25, 50, 100])
skip: int = Field(default=0, examples=[0, 10, 50])
class FilterParams(BaseModel, PageParams, ReleaseFilter):
extra_parameter_1: str | None = None
extra_parameter_2: str | None = None
@app.get("/items/")
async def read_items(filter_query: Annotated[FilterParams, Query()]):
return filter_query |
Beta Was this translation helpful? Give feedback.
-
Beta Was this translation helpful? Give feedback.
-
|
After digging around for quite bit trying to get Query Parameter Models to work, I found a kind of hacky workaround that seems to support most of the features I needed. All the workarounds I've seen in other comments didn't work with one or more of these features.
Note that the models are annotated with from typing import Literal, Annotated, Any, Callable, get_args, get_origin
from fastapi import Depends, FastAPI, Query, params
from pydantic import BaseModel, Field, dataclasses, ConfigDict
import inspect
def query_parameter_model[T: Callable[..., object]](klass: T) -> T:
"""Define this decorator in util module"""
aliases: dict[str, str] = {}
for name, annotation in inspect.get_annotations(klass).items():
if get_origin(annotation) is Annotated:
for ann_arg in get_args(annotation):
if isinstance(ann_arg, params.Query):
if ann_arg.alias:
aliases[name] = ann_arg.alias
return dataclasses.dataclass(
config=ConfigDict(
alias_generator=lambda name: aliases.get(name, name),
validate_by_alias=True,
validate_by_name=True,
)
)(klass)
app = FastAPI()
@query_parameter_model
class FilterParams:
limit: Annotated[int, Query(gt=0, le=100)] = 100
offset: Annotated[int, Query(ge=0)] = 0
order_by: Annotated[Literal["created_at", "updated_at"], Query(alias="order-by")] = "created_at"
tags: Annotated[list[str], Query(default_factory=list)] = Field()
@query_parameter_model
class I18nParams:
lang_id: Annotated[str, Query(alias="lang-id")] = "en"
currency_format: Annotated[str | None, Query(alias="curr-fmt")] = None
def verify_i18n(i18n_params: Annotated[I18nParams, Depends()]) -> bool:
# Verify that currency_format is valid for the given lang_id
return i18n_params.lang_id == "en" and i18n_params.currency_format == "USD"
@app.get("/items/")
async def read_items(
filter_params: Annotated[FilterParams, Depends()],
i18n_params: Annotated[I18nParams, Depends()],
verify_i18n: Annotated[bool, Depends(verify_i18n)],
item_id: Annotated[int | None, Query(alias="item-id")] = None,
) -> Any:
return {
"item_id": item_id,
"filter_params": filter_params,
"i18n_params": i18n_params,
"verify_i18n": verify_i18n,
"constructed": I18nParams(lang_id="fr", currency_format="EUR"),
"constructed_w_alias": I18nParams(**{"lang-id": "fr", "currency-format": "EUR"}),
# "constructed_bad": FilterParams(limit=1000), # raises validation error as expected
}
I'll also try to document all the other workarounds from other comments and which feature didn't work with them.
|
Beta Was this translation helpful? Give feedback.



Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
First Check
Commit to Help
Example Code
Description
results in
so now the docs dont appear as in
https://fastapi.tiangolo.com/tutorial/query-param-models/#query-parameters-with-a-pydantic-model
Operating System
Windows
Operating System Details
No response
FastAPI Version
0.115.11
Pydantic Version
2.8.1
Python Version
3.11.10
Additional Context
No response
Beta Was this translation helpful? Give feedback.
All reactions