question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Pydantic Wrapped List Query Parameters in Body Instead of Query

See original GitHub issue

First Check

  • I added a very descriptive title to this issue.
  • I used the GitHub search to find a similar issue and didn’t find it.
  • I searched the FastAPI documentation, with the integrated search.
  • I already searched in Google “How to X in FastAPI” and didn’t find any information.
  • I already read and followed all the tutorial in the docs and didn’t find an answer.
  • I already checked if it is not related to FastAPI but to Pydantic.
  • I already checked if it is not related to FastAPI but to Swagger UI.
  • I already checked if it is not related to FastAPI but to ReDoc.

Commit to Help

  • I commit to help with one of those options 👆

Example Code

from typing import List, Optional
from fastapi import FastAPI, Query, Depends
from pydantic import BaseModel

app = FastAPI()

class Querymodel(BaseModel):
    problematic: Optional[List[str]] = Query([])
    okay: Optional[str] = Query(None)

@app.get("/")
async def root(select: List[str] = Query(None), queries: Querymodel = Depends()):
    return {"select": select, "queries": queries}

Description

Re-production:

  • Open the browser and navigate to the swagger or redoc page (/docs or /redoc)

  • See that the get root endpoint offers the query parameters: select and okay

  • See that the request has a body that contains the default value of the problematic Query object

  • Execute a GET request to: /?select=string&select=string&okay=hello&problematic=string&problematic=string

  • See that the problematic field is returned empty, but all others are correctly populated

Expected Behavior:

  • All 3 Query parameters are shown and are usable.

Operating System

Linux

Operating System Details

Ubuntu 20.04.3 LTS

FastAPI Version

0.72.0

Python Version

3.8.12

Additional Context

The intent was to wrap a significant number of query parameters (some of which are lists) inside of a pydantic model in order to reduce the size of the method signature. Unwrapping the Query objects into the signature results in the expected behavior, of all query parameters being present.

I’ve looked at https://github.com/tiangolo/fastapi/issues/321 as it seems to be the closest to my question, but am unable to identify further parallels than use of the explicit Query object declaration.

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Reactions:6
  • Comments:6

github_iconTop GitHub Comments

3reactions
fnepcommented, May 4, 2022

I also have this as an issue. I hesitate to call it bug, because i also cannot really find this in the documentation. I found it through StackOverflow and for me it really solves a problem.

From my understanding, the issue is somewhere in the fastapi.dependencies.utils.get_dependant function, where somehow the details are lost when adding the sub_dependant. Anyhow, i don’t know FastApi well enough to commit a pull request for this.

As a workaround, one can simply wrap the Query() call in a Field() call (give it as default parameter to Field). This way, the Query survives and is added as expected also with details like the description or examples.

So, this may work for you:

 from typing import List, Optional
 from fastapi import FastAPI, Query, Depends
-from pydantic import BaseModel
+from pydantic import BaseModel, Field

 app = FastAPI()

 class Querymodel(BaseModel):
-    problematic: Optional[List[str]] = Query([])
+    problematic: Optional[List[str]] = Field(Query([]))
     okay: Optional[str] = Query(None)

 @app.get("/")
 async def root(select: List[str] = Query(None), queries: Querymodel = Depends()):
     return {"select": select, "queries": queries}

I also drafted a simple metaclass to automate this, hoping to make it easier to remove later, in case this is solved in FastApi.

 from typing import List, Optional
 from fastapi import FastAPI, Query, Depends
-from pydantic import BaseModel
+from pydantic import BaseModel, Field
+from pydantic.main import ModelMetaclass
+
+class AllFields(ModelMetaclass):
+    def __new__(self, name, bases, namespaces, **kwargs):
+        for field in namespaces:
+            if not field.startswith("__"):
+                namespaces[field] = Field(namespaces[field])
+        return super().__new__(self, name, bases, namespaces, **kwargs)

 app = FastAPI()

-class Querymodel(BaseModel):
+class Querymodel(BaseModel, metaclass=AllFields):
     problematic: Optional[List[str]] = Query([])
     okay: Optional[str] = Query(None)

 @app.get("/")
 async def root(select: List[str] = Query(None), queries: Querymodel = Depends()):
     return {"select": select, "queries": queries}
0reactions
Akkarinecommented, Aug 11, 2022

I faced the same issue and that comment: https://github.com/tiangolo/fastapi/issues/2869#issuecomment-786729484 helped me. Dataclasses solved this problem. But don’t inherit dataclasses from Pydantic models, as said in docs. If you override class attributes, somehow in init order of inheritance is lost, so your instance get attributes like they are in parent class (not overrided).

Read more comments on GitHub >

github_iconTop Results From Across the Web

fastapi+pydantic query parameter checking for complex ...
In fastapi path definitions I currently define filter , sort , and range as strings as in the code below, convert them using...
Read more >
Query Parameters and String Validations - FastAPI
Pydantic, which is what powers all the data validation and serialization in FastAPI, has a special behavior when you use Optional or Union[Something,...
Read more >
How we validate input data using pydantic
We use the Python package pydantic for fast and easy validation of input data. Here's how.
Read more >
how to pass multiple parameters in post request in restful web ...
The problem is that JSON sent in the HTTP request body is marshaled to the first method parameter Your other parameters did not...
Read more >
Advanced Usage - webargs 8.2.0 documentation
For example, to mix query parameters and form body data, you might write the ... you can pass a marshmallow Schema instead of...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found