redis / redis-om-python

Object mapping, and more, for Redis and Python
MIT License
1.06k stars 108 forks source link

FastAPI (v0.100.0) / Pydantic v2 incompatibility #539

Closed ninoseki closed 2 months ago

ninoseki commented 12 months ago

I'm sorry I think I made a mistake in #533. I misunderstood that FastAPI (v0.100.0) has a compatibility in Pydantic v1 & v2 and it can use both versions as a response model & response body. But it doesn't.

For example, the following code fails because the latest FastAPI does not allow using Pydantic v1 as a response model & body class.

# test.py
import datetime
from typing import Optional

from fastapi import FastAPI
from redis_om import HashModel, get_redis_connection

REDIS_DATA_URL = "redis://localhost:6380"

class Customer(HashModel):
    first_name: str
    last_name: str
    email: str
    join_date: datetime.date
    age: int
    bio: Optional[str]

app = FastAPI()

@app.post("/customer")
async def save_customer(customer: Customer):
    return customer.save()

@app.get("/customers")
async def list_customers():
    return {"customers": Customer.all_pks()}

@app.on_event("startup")
async def startup():
    Customer.Meta.database = get_redis_connection(
        url=REDIS_DATA_URL, decode_responses=True
    )
  File "/Users/foo/test.py", line 32, in <module>
    @app.post("/customer")
  File "/Users/foo/ib/python3.11/site-packages/fastapi/routing.py", line 706, in decorator
  self.add_api_route(
  File "/Users/foo/ib/python3.11/site-packages/fastapi/routing.py", line 645, in add_api_route
  route = route_class(
  ^^^^^^^^^^^^
  File "/Users/foo/ib/python3.11/site-packages/fastapi/routing.py", line 491, in **init**
  self.dependant = get_dependant(path=self.path_format, call=self.endpoint)
  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/foo/ib/python3.11/site-packages/fastapi/dependencies/utils.py", line 261, in get_dependant
  type_annotation, depends, param_field = analyze_param(
  ^^^^^^^^^^^^^^
  File "/Users/foo/ib/python3.11/site-packages/fastapi/dependencies/utils.py", line 429, in analyze_param
  field = create_response_field(
  ^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/foo/ib/python3.11/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 'test.Customer'> 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/

There is a workaround like the following.

# Pydantic v2
class CustomerWrapper(BaseModel):
    first_name: str
    last_name: str
    email: str
    join_date: datetime.date
    age: int
    bio: Optional[str]

app = FastAPI()

@app.post("/customer")
async def save_customer(customer: CustomerWrapper):
    db_obj = Customer.parse_obj(customer.model_dump())
    return db_obj.save()

But I think it's not good.

So it will be better to revert #533 if the FastAPI support has the high priority in this library. Again, sorry for my careless.

XChikuX commented 12 months ago

Appreciate the honesty. What's the most recent working version of FastAPI? Will 0.1.4 still work with pydantic v1?

Update: I checked pydantic v1 with FastAPI 0.100.0 Everything, seems to work fine. I think the problem is just with v2.

ninoseki commented 12 months ago

Yes you can use the latest FastAPI (v0.100.0) with Pydantic v1. The latest redis-om can handle Pydantic v1 too. So the following dependencies are safe to use.

fastapi = "0.100.0"
pydantaic = ">=1.10.2,<2.0"
redis-om = "0.1.3"
PARKER-X commented 10 months ago

I got similar error @ninoseki How can i handle if i use post method it gives me save is not working it's my first time of using redis plz help

dgtlmonk commented 9 months ago

I got similar error @ninoseki How can i handle if i use post method it gives me save is not working it's my first time of using redis plz help

pip install pydantic==1.10.13 should solve your problem

valentina-buoro commented 8 months ago

thanks @dgtlmonk ! It worked for me