Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Silently add __root__ or document the Pydantic dependency #2909

Closed
snow6oy opened this issue Mar 7, 2021 · 5 comments
Closed

Silently add __root__ or document the Pydantic dependency #2909

snow6oy opened this issue Mar 7, 2021 · 5 comments
Labels
question Question or problem question-migrate

Comments

@snow6oy
Copy link

snow6oy commented Mar 7, 2021

Example

from pydantic import BaseModel
from typing import Dict

class Banana(BaseModel):
    whatever: float
    foo: str
class Bananas(BaseModel):
    __root__: Dict[str, Banana]

app = FastAPI()

@app.post("/bananas")
async def post_bananas(b: Bananas):
  print(b.dict())   # returns a dictionary:

Description

When defining a Pydantic model with a custom root I would like it so that either:

  • A. The example displayed by FastAPI at /docs displays the "root" key that my client needs to send OR (even better)

  • B. The client does not receive a 422 error when the key is omitted and instead FastAPI silently provides it for me

  • Open the browser and call the endpoint localhost:8000/docs.

  • It displays a JSON example with { "additionalProp1": { "whatever": 0, "foo": "string" }, "additionalProp2": { "whatever": 0, "foo": "string" }, "additionalProp3": { "whatever": 0, "foo": "string" } }.

  • But I expected it to prefix with {"__root__": "{ ...}" }.

Environment

  • OS: Ubunut 20.04.2
  • FastAPI Version 0.61.2
  • Python version: 3.8.5

Additional context

@snow6oy snow6oy added the question Question or problem label Mar 7, 2021
@ycd
Copy link
Contributor

ycd commented Mar 7, 2021

The example displayed by FastAPI at /docs displays the "root" key that my client needs to send OR (even better)

That was added #1524.

The client does not receive a 422 error when the key is omitted and instead FastAPI silently provides it for me

Expected behaviour since the syntax looks valid.

It displays a JSON example with { "additionalProp1": { "whatever": 0, "foo": "string" }, "additionalProp2": { "whatever": 0, "foo": "string" }, "additionalProp3": { "whatever": 0, "foo": "string" } }.

Again, valid according to your model, and FastAPI has no idea about what is going on here. See the schema of your model.

>>> your_model.schema()
{'title': 'Bananas', 'type': 'object', 'additionalProperties': {'$ref': '#/definitions/Banana'}, 'definitions': {'Banana': {'title': 'Banana', 'type': 'object', 'properties': {'whatever': {'title': 'Whatever', 'type': 'number'}, 'foo': {'title': 'Foo', 'type': 'string'}}, 'required': ['whatever', 'foo']}}}

There is nothing called __root__.

But I expected it to prefix with {"root": "{ ...}" }

You are missing that __root__ is the object actually. It is not a key to a value, __root__ is the object itself for Pydantic models. You can use it like this when initilazing your model that with custom __root__,

 Bananas(__root__={"dummy": {"whatever": 12.3, "foo": "abc"}})

But the __root__ is not something that you can use as key to a value.

@snow6oy
Copy link
Author

snow6oy commented Mar 8, 2021

image

Sorry, I am not understanding your reply. Release #1524 squashed the __root__ in the response, but I was requesting it be displayed as an Example Value in the request. As the screenshot shows, it is not displayed by FastAPI.

image
If I now hit Execute using this example I get a 422 returned. As shown by the above screenshot. This is confusing, because as you say the data is valid to the model. So what is the error?

Finally, you said that should not use __root__ as a key to the value. Only by trial and error did I discover this trick. I don't think it's the right way either, but If there is a better way I still don't know what it is. Your example makes sense using Pydantic at the command line, but how do I say

Bananas(__root__={"dummy": {"whatever": 12.3, "foo": "abc"}})

when the model is initialised using a function call

async def post_bananas(b: Bananas(__root__= ??? ):

Thanks for patience 😄

@snow6oy
Copy link
Author

snow6oy commented Mar 8, 2021

image

Here's a screenshot of the success request. And again as curl

curl -X POST "http://localhost:8002/bananas" -H  "accept: application/json" -H  "Content-Type: application/json" -d "{\"__root__\":{\"additionalProp1\":{\"whatever\":0,\"foo\":\"string\"},\"additionalProp2\":{\"whatever\":0,\"foo\":\"string\"},\"additionalProp3\":{\"whatever\":0,\"foo\":\"string\"}}}"

I am curious to know if you see the same on your setup.

@tiangolo
Copy link
Owner

Thanks for the help @ycd! 🙇

@snow6oy In FastAPI you would rarely need/want to use __root__. You can use the standard type annotations directly:

from pydantic import BaseModel

class Banana(BaseModel):
    whatever: float
    foo: str

app = FastAPI()

@app.post("/bananas")
async def post_bananas(b: dict[str, Banana]):
  print(b)   # returns a dictionary:

I would think that's probably a better solution to the final intention (independent of __root__'s behavior).

Sorry for the long delay! 🙈 I wanted to personally address each issue/PR and they piled up through time, but now I'm checking each one in order.

@github-actions
Copy link
Contributor

github-actions bot commented Dec 5, 2022

Assuming the original need was handled, this will be automatically closed now. But feel free to add more comments or create new issues or PRs.

@github-actions github-actions bot closed this as completed Dec 5, 2022
@tiangolo tiangolo reopened this Feb 27, 2023
@github-actions github-actions bot removed the answered label Feb 27, 2023
Repository owner locked and limited conversation to collaborators Feb 27, 2023
@tiangolo tiangolo converted this issue into discussion #6897 Feb 27, 2023

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Labels
question Question or problem question-migrate
Projects
None yet
Development

No branches or pull requests

3 participants