✨ Support for mixed and multiple Pydantic models for parameters using Query, Cookie and Header#12481
✨ Support for mixed and multiple Pydantic models for parameters using Query, Cookie and Header#12481JSCU-CNI wants to merge 8 commits intofastapi:masterfrom
Conversation
|
Thanks for the PR! As you consider this to be a bug, can you commit a unit test that shows the behaviour of this functionality on this PR, which would break on |
e851c68 to
792ee21
Compare
|
@svlandeg I've updated the PR with more tests, and fixed something uncovered by those tests 👍 |
|
Looking forward to this, it fixes the issue described in this comment #12199 (comment) |
|
Reflecting on this, I believe we could classify this as a feature rather than a bug. For the first test case, i.e. It now properly handles multiple Pydantic models, dependencies and direct arguments. I've updated the PR title to reflect this. |
|
Would love to see this merged, the query param models are mostly unusable for us in their current state |
|
Also waiting for this to be merged 😺 |
|
@svlandeg Is there anything we can do to move this PR forward? |
|
Hi! We really appreciate the time and effort spent to submit this PR. We have a high volume of PRs and we're working hard to review and classify them. We'll get back to you once we've been able to review this in detail - thanks for your patience! 🙏 |
|
Hi everyone! Any updates on this PR? |
792ee21 to
86d9bb1
Compare
|
@JSCU-CNI, thank you for your work! I haven't delved into the implementation details yet, just looked at it briefly. As I can see, the case with One more thing to think about: if we have 2 models and both of them have field with the same name, will this be handled well? Intuitively, everything should be Ok, but better check it and probably add test to make it explicit. |
fb793e7 to
39241de
Compare
|
Thank you for your comment @YuriiMotov. The implementation closely follows the original code, and only makes some necessary adjustments. It's no coincidence that PR #12944 closely resembles this code, as they probably did a similar thing. Regarding your comment on You're correct that everything functions properly when there are overlapping field names in different models, but I've added several test cases to verify this as well. I've rebased and squashed all commits, and added some comments to the test cases to explain them a bit better. I've also added a test where I mix various models, just to fully cover our bases. |
|
@JSCU-CNI, thanks for the explanation! One more thing. There are no tests for class Model3(BaseModel):
field_1: str
class Model4(BaseModel):
field_2: str
@app.get("/headers2")
async def get_hhh(
h1: Annotated[Model3, Header(convert_underscores=False)],
h2: Annotated[Model4, Header(convert_underscores=False)],
):
return {"h1": h1, "h2": h2}Shows parameters as |
23b5d4c to
d65888d
Compare
|
Could this solution be extended to cover Form() parameters also? We're building an app using HTMX that is intended to degrade gracefully in situations without Javascript (so no AJAX, no JSON) and it would be extremely convenient to POST one flat form and have the backend automatically generate separate Pydantic models for us. |
|
Looking forward to this being merged. I expected this to work as described going off of the documentation. Thanks for the work to all involved. |
This comment was marked as resolved.
This comment was marked as resolved.
|
Looking forward as well, this will allow us to combine filters with |
00693fd to
f799a56
Compare
f799a56 to
32a5220
Compare
…g Query, Cookie and Header From fastapi#12199 onwards, Pydantic models are supported for query, cookie and header parameters. When one parameter is present, the model is flattened in the OpenAPI spec, but when multiple are defined, they aren't. This is confusing, and results in a confusing OpenAPI spec. Since these arguments are used in flattened form anyway, it makes more sense to flatten all of them.
32a5220 to
6aa2546
Compare
|
This change is crucial for our team, many thanks to all those involved! 🙏 It's difficult to take full advantage of |
There was a problem hiding this comment.
The implementation here looks clean, and I agree that flattening multiple Pydantic models alongside eachother feels like the most intuitive thing, considering how this works with a single model.
This is a breaking change though - old code using either one Pydantic model + additional atomic parameters, or multiple Pydantic models, will now behave differently. Maybe @YuriiMotov 's idea of introducing a flatten= parameter would help users preserve existing functionality in case they'd want it?
With respect to the docs: I don't see any pages that require updating. But we should definitely include some kind of warning in the release notes. And maybe add a docs example of using multiple models, and explain how they'd be flattened? (this can be added in a follow-up PR)
@JSCU-CNI : thank you for the time and effort you've already put into this PR! Appreciate the responsiveness and clear communication. I also think this PR has gotten a lot stronger already from you adressing @YuriiMotov's comments 🙏
|
It would be great if Tiangolo can have a final look at this before we merge, I've solicited his feedback 🙏 |
From #12199 onwards, Pydantic models are supported for query, cookie and header parameters. When one parameter is present, the model is flattened in the OpenAPI spec, but when multiple are defined, they aren't.
This is confusing, and results in a confusing OpenAPI spec. Since these arguments are used in flattened form anyway, it makes more sense to flatten all of them.