Skip to content
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

Working with Pydantic v1 while having v2 installed #10360

Open
Kludex opened this issue Oct 1, 2023 Discussed in #9966 · 8 comments
Open

Working with Pydantic v1 while having v2 installed #10360

Kludex opened this issue Oct 1, 2023 Discussed in #9966 · 8 comments

Comments

@Kludex
Copy link
Member

Kludex commented Oct 1, 2023

Discussed in #9966

Originally posted by slafs July 29, 2023
This is a continuation of a topic introduced in #9709 (comment) as requested by @Kludex. I've chosen the "Show and tell" category as the (lack of) template seems better for this discussion.

In the original thread I've asked if there's a way to work with pydantic v1 while having v2 installed:

Pydantic v2 ships the latest version of v1 for easier migration, so the pattern is to work with v1 via things like from pydantic.v1 import BaseModel etc. while having v2 installed.

Currently, this approach doesn't seem to work with FastAPI 0.100.0 and the following snippet:

from fastapi import FastAPI

from pydantic.v1 import BaseModel


class Model(BaseModel):
    foo: str = "foo"
    bar: int = 2


app = FastAPI()


@app.get("/")
def root(model: Model) -> Model:
    return model

produces the following error:

Traceback (most recent call last):
  File ".../fiddles/fastapi_pydantic_v1_on_v2.py", line 15, in <module>
    def root(model: Model) -> Model:
  File ".../lib/python3.10/site-packages/fastapi/routing.py", line 706, in decorator
    self.add_api_route(
  File ".../lib/python3.10/site-packages/fastapi/routing.py", line 645, in add_api_route
    route = route_class(
  File ".../lib/python3.10/site-packages/fastapi/routing.py", line 448, in __init__
    self.response_field = create_response_field(
  File ".../lib/python3.10/site-packages/fastapi/utils.py", line 101, in create_response_field
    raise fastapi.exceptions.FastAPIError(
fastapi.exceptions.FastAPIError: Invalid args for response field! Hint: check that <class '__main__.Model'> is a valid Pydantic field type. If you are using a return type annotation that is not a valid Pydantic field (e.g. Union[Response, dict, None]) you can disable generating the response model from the type annotation with the path operation decorator parameter response_model=None. Read more: https://fastapi.tiangolo.com/tutorial/response-model/

Switching from pydantic.v1 to just pydantic (v2) obviously works.

I'm seeing there's fastapi._compat module and PYDANTIC_V2 var, but I'm not sure if that's the right direction.

For reference, installed versions:

fastapi==0.100.0
pydantic==2.0.3
pydantic_core==2.3.0

Now... that being said, I'm not even sure if this would be helpful to anyone even if FastAPI did support it. My initial thought was that this would ease the migration, but the reality seems more complicated. E.g. models are used by other models and even Pydantic itself doesn't support mixing v1 and v2 together. So given that the cost of figuring out the plan for the gradual migration seems comparable with doing the whole migration at once (at least for us).

Maybe it would be useful if people commented on their intended use case and see if that's actually a feature that's needed/wanted.

@chbndrhnns
Copy link

In case it helps, I started PR about that:
#10223

@mike0sv

This comment was marked as spam.

@fastapi fastapi locked as spam and limited conversation to collaborators Oct 3, 2023
@fastapi fastapi unlocked this conversation Apr 11, 2024
@dariota
Copy link

dariota commented Aug 23, 2024

Maybe it would be useful if people commented on their intended use case and see if that's actually a feature that's needed/wanted.

It seems people have been primarily doing that on #10223 and in issues opened against a heap of other projects (see above).
In short, not supporting the pydantic.v1 models completely blocks codebases that can't be upgraded all in one go to pydantic v2 (not practical in larger codebases, and the bump-pydantic tool misses many issues), which prevents people either from upgrading to pydantic v2 (which, at least based on its docs, seems like a solid improvement on v1) or keeps people on old versions of fastapi.

It also means that FastAPI doesn't really support pydantic v1 as indicated here. Specifically, it doesn't really support pydantic v2, since the backwards compatibility with pydantic v1 models is an important feature of that version allowing progressive upgrades.

Unfortunately that PR, though well-intentioned, appears to be abandoned. It's a bit lacking in detail as to what's left to be done or why it's not ready to merge, so it seems unlikely anyone'll be able to pick it up either - which given the amount of people asking about its status might otherwise have happened, though I'm under no illusion that it's much easier to ask about progress than to act on it yourself 😄

@chbndrhnns
Copy link

Unfortunately that PR, though well-intentioned, appears to be abandoned.

If you talk about PR #10223, it was complete IMO at the time of creation but sadly never got any response from @tiangolo.
I am willing to rebase it but not without feedback.

@derekahuang
Copy link

@tiangolo Any update on this issue??

@tomtom103
Copy link

Any way of getting some visibility here? It’s currently very hard to migrate for large code bases.

@EldarSehayekZenity
Copy link

EldarSehayekZenity commented Oct 16, 2024

Joining the thread as well, I'm WIP updating from Pydantic V1 to V2 on a massive code base with dozens of FastAPI routes and hundreds of models. I use the "from pydantic.v1 import BaseModel" approach, however I have failures to generate OpenApi schema using FastAPI "get_openapi" utility since the schema generation fails when encountering a field with Pydantic V1 @validator decorator which is treated as a field instead of being ignored by the schema generator.

@Kilo59
Copy link

Kilo59 commented Oct 16, 2024

A good compromise might be if the pydantic v1 vs v2 logic was applied per APIRouter.
Each router can use either Pydantic V1 models or V2 models, but not use both simultaneously.

Devs with a large code base can then migrate per router (and, if need be, break up their app to use multiple routers).

This assumes that implementing this at the APIRouter level is easier/more maintainable.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants