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.

Use pydantic model saved in __init__ to check request input in a __call__ dependency

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.
  • After submitting this, I commit to one of:
    • Read open issues with questions until I find 2 issues where I can help someone and add a comment to help there.
    • I already hit the “watch” button in this repository to receive notifications and I commit to help at least 2 people that ask questions in the future.
    • Implement a Pull Request for a confirmed bug.

Example

Here’s a self-contained, minimal, reproducible, example with my use case:

##############################
# file models.py

from pydantic import BaseModel


class ExampleModel(BaseModel):
    example: str


##############################
# file dependencies.py

from pydantic import BaseModel


class ExampleClass:
    # BaseModel just for editor suggestions, model will always be a class inherited from BaseModel, A.K.A a pydantic model
    def __init__(self, model: BaseModel) -> None:
        self.model = model

    async def __call__(self, input: self.model):
        return 'Hello, this is an example. An 422 should be raised if input doesn't match the model'


##############################
# file api.py
from .dependencies import ExampleClass
from .models import ExampleModel


example_dependency = ExampleClass(ExampleModel)

@router.post('/')
async def example_endpoint(payload = Depends(example_dependency)):
    return payload

Description

My question is in file dependencies.py at call method, I cannot use self.model as a type hint because self is not defined yet, but I want this method to automatically return the 422 FastAPI returns when a model is not matched.

The reason why I’m not directly using the ExampleModel itself is that I want ExampleClass to be independent of the input, so I can reuse it as a dependency for multiple methods.

Environment

  • OS: Linux Kubuntu
  • FastAPI Version: 0.65.1
  • Python version: 3.9.4

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:7

github_iconTop GitHub Comments

1reaction
dreinoncommented, Jul 14, 2021

Closing this issue because a new one has been opened to discuss the specific topic.

0reactions
dreinoncommented, Jul 13, 2021

You could try declaring a TypeVar to make the ExampleClass generic.

from typing import Type, TypeVar

from fastapi import APIRouter, Depends
from pydantic import BaseModel

router = APIRouter()

T = TypeVar("T", bound=BaseModel)


class ExampleModel(BaseModel):
    example: str


class ExampleClass:
    # BaseModel just for editor suggestions, model will always be a class
    # inherited from BaseModel, A.K.A a pydantic model
    def __init__(self, model: Type[T]) -> None:
        self.model = model

    async def __call__(self, input: Type[T]):
        return (
            "Hello, this is an example. An 422 should be raised if input "
            "doesn't match the model"
        )


example_dependency = ExampleClass(ExampleModel)


@router.post("/")
async def example_endpoint(payload=Depends(example_dependency)):
    return payload

Using this code, call / with payload

{
    "example": "value"
}

and you will get a 422 response with the following message:

{
  "detail": [
    {
      "loc": [
        "query",
        "input"
      ],
      "msg": "field required",
      "type": "value_error.missing"
    }
  ]
}

which is asking for a query parameter called input. This is due to the way FastAPI recognises parameters, which according to the docs is:

The function parameters will be recognized as follows:

  1. If the parameter is also declared in the path, it will be used as a path parameter.
  2. If the parameter is of a singular type (like int, float, str, bool, etc) it will be interpreted as a query parameter.
  3. If the parameter is declared to be of the type of a Pydantic model, it will be interpreted as a request body.

Since T is a custom type, pydantic is recognising it as a query parameter (2), even though T is actually a pydantic model, and thus, it should be recognised as the request body (3).

Read more comments on GitHub >

github_iconTop Results From Across the Web

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 use a Pydantic model with Form data in FastAPI?
The first step to working out what's going wrong is to inspect the POST request and see what's being submitted. – SColvin. Feb...
Read more >
Cool Things You Can Do With Pydantic - Medium
Pydantic is a useful library for data parsing and validation. It coerces input types to the declared type (using type hints), accumulates all ......
Read more >
Settings management - pydantic
If you create a model that inherits from BaseSettings , the model initialiser will attempt to determine the values of any fields not...
Read more >
The Beginner's Guide to Pydantic. A Python package to parse ...
The topic for today is on data validation and settings management using Python type hinting. We are going to use a Python package...
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