pydantic-sqlalchemy icon indicating copy to clipboard operation
pydantic-sqlalchemy copied to clipboard

Multiple schemas from same model give KeyError on model_name_map

Open adityagupta1089 opened this issue 4 years ago • 3 comments

MWE: (main.py)

from fastapi import FastAPI
from pydantic_sqlalchemy import sqlalchemy_to_pydantic
from sqlalchemy import Column, Integer, String, create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import Session, sessionmaker

Base = declarative_base()

engine = create_engine("sqlite://", echo=True)


class User(Base):
    __tablename__ = "users"

    id = Column(Integer, primary_key=True)
    name = Column(String)


PydanticUser1 = sqlalchemy_to_pydantic(User)
PydanticUser2 = sqlalchemy_to_pydantic(User, exclude=["id"])

Base.metadata.create_all(engine)

LocalSession = sessionmaker(bind=engine)

db: Session = LocalSession()

app = FastAPI()


@app.get("/user1", response_model=PydanticUser1)
def get_user1():
    return {"Hello": "World"}


@app.get("/user2", response_model=PydanticUser2)
def get_user2():
    return {"Hello": "World"}

Output: (uvicorn main:app --reload)

IINFO:     Started server process [149476]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
INFO:     127.0.0.1:43332 - "GET /docs HTTP/1.1" 200 OK
INFO:     127.0.0.1:43332 - "GET /openapi.json HTTP/1.1" 500 Internal Server Error
ERROR:    Exception in ASGI application
Traceback (most recent call last):
  File "./venv/lib/python3.9/site-packages/uvicorn/protocols/http/h11_impl.py", line 394, in run_asgi
    result = await app(self.scope, self.receive, self.send)
  File "./venv/lib/python3.9/site-packages/uvicorn/middleware/proxy_headers.py", line 45, in __call__
    return await self.app(scope, receive, send)
  File "./venv/lib/python3.9/site-packages/fastapi/applications.py", line 199, in __call__
    await super().__call__(scope, receive, send)
  File "./venv/lib/python3.9/site-packages/starlette/applications.py", line 111, in __call__
    await self.middleware_stack(scope, receive, send)
  File "./venv/lib/python3.9/site-packages/starlette/middleware/errors.py", line 181, in __call__
    raise exc from None
  File "./venv/lib/python3.9/site-packages/starlette/middleware/errors.py", line 159, in __call__
    await self.app(scope, receive, _send)
  File "./venv/lib/python3.9/site-packages/starlette/exceptions.py", line 82, in __call__
    raise exc from None
  File "./venv/lib/python3.9/site-packages/starlette/exceptions.py", line 71, in __call__
    await self.app(scope, receive, sender)
  File "./venv/lib/python3.9/site-packages/starlette/routing.py", line 566, in __call__
    await route.handle(scope, receive, send)
  File "./venv/lib/python3.9/site-packages/starlette/routing.py", line 227, in handle
    await self.app(scope, receive, send)
  File "./venv/lib/python3.9/site-packages/starlette/routing.py", line 41, in app
    response = await func(request)
  File "./venv/lib/python3.9/site-packages/fastapi/applications.py", line 152, in openapi
    return JSONResponse(self.openapi())
  File "./venv/lib/python3.9/site-packages/fastapi/applications.py", line 130, in openapi
    self.openapi_schema = get_openapi(
  File "./venv/lib/python3.9/site-packages/fastapi/openapi/utils.py", line 354, in get_openapi
    definitions = get_model_definitions(
  File "./venv/lib/python3.9/site-packages/fastapi/utils.py", line 28, in get_model_definitions
    model_name = model_name_map[model]
KeyError: <class 'pydantic.main.User'>

adityagupta1089 avatar Jan 07 '21 11:01 adityagupta1089

Having the same issue. We want to use it as such: PydanticTesting = sqlalchemy_to_pydantic(Testing) PydanticCreateTesting = sqlalchemy_to_pydantic(Testing, exclude=['id']) PydanticUpdateTesting = sqlalchemy_to_pydantic(Testing, exclude=['id', 'company_id'])

We want to use PydanticCreateTesting or PydanticUpdateTesting as body parameters for POST and PUT requests, and PydanticTesting as the response_model.

kl-sento avatar Jun 16 '21 12:06 kl-sento

a hacky solution, not sure if it is 100% correct but it works

PydanticUser1 = sqlalchemy_to_pydantic(User)
PydanticUser1.__name__ = "PydanticUser1"
PydanticUser2 = sqlalchemy_to_pydantic(User, exclude=["id"])
PydanticUser2.__name__ = "PydanticUser2"

a-atalla avatar Sep 17 '21 20:09 a-atalla

The Problem is, that FastAPI is using a Dictionary with the ModelClassName aka name as a Index. This isn't a Problem of the package itself.

devmaxde avatar Jun 26 '22 08:06 devmaxde