Issue
Currently, we use Python 3.12, sqlmodel==0.0.14, and pydantic==2.5.2. The code below works with older sqlmodel versions and pydantic=1.x. However, once we upgrade to the very recent versions the following errors show up.
When executing
from typing import List, Optional
from sqlmodel import Field, Relationship, SQLModel
class HeroTeamLink(SQLModel, table=True):
team_id: Optional[int] = Field(
default=None, foreign_key="team.id", primary_key=True
)
hero_id: Optional[int] = Field(
default=None, foreign_key="hero.id", primary_key=True
)
class Team(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
name: str = Field(index=True)
headquarters: str
heroes: List["Hero"] = Relationship(back_populates="teams", link_model=HeroTeamLink)
class Hero(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
name: str = Field(index=True)
secret_name: str
age: Optional[int] = Field(default=None, index=True)
teams: List[Team] = Relationship(back_populates="heroes", link_model=HeroTeamLink)
class HeroOut(Hero):
is_new: bool = Field(default=False)
we get the following error:
fastapi_test_app-web-1 | /usr/local/lib/python3.12/site-packages/pydantic/_internal/_fields.py:184: UserWarning: Field name "teams" shadows an attribute in parent "Hero";
fastapi_test_app-web-1 | warnings.warn(
fastapi_test_app-web-1 | /usr/local/lib/python3.12/site-packages/pydantic/_internal/_fields.py:184: UserWarning: Field name "id" shadows an attribute in parent "Hero";
fastapi_test_app-web-1 | warnings.warn(
fastapi_test_app-web-1 | /usr/local/lib/python3.12/site-packages/pydantic/_internal/_fields.py:184: UserWarning: Field name "name" shadows an attribute in parent "Hero";
fastapi_test_app-web-1 | warnings.warn(
fastapi_test_app-web-1 | /usr/local/lib/python3.12/site-packages/pydantic/_internal/_fields.py:184: UserWarning: Field name "secret_name" shadows an attribute in parent "Hero";
fastapi_test_app-web-1 | warnings.warn(
fastapi_test_app-web-1 | /usr/local/lib/python3.12/site-packages/pydantic/_internal/_fields.py:184: UserWarning: Field name "age" shadows an attribute in parent "Hero";
fastapi_test_app-web-1 | warnings.warn(
fastapi_test_app-web-1 | Process SpawnProcess-1:
fastapi_test_app-web-1 | Traceback (most recent call last):
fastapi_test_app-web-1 | File "/usr/local/lib/python3.12/multiprocessing/process.py", line 314, in _bootstrap
fastapi_test_app-web-1 | self.run()
fastapi_test_app-web-1 | File "/usr/local/lib/python3.12/multiprocessing/process.py", line 108, in run
fastapi_test_app-web-1 | self._target(*self._args, **self._kwargs)
fastapi_test_app-web-1 | File "/usr/local/lib/python3.12/site-packages/uvicorn/_subprocess.py", line 76, in subprocess_started
fastapi_test_app-web-1 | target(sockets=sockets)
fastapi_test_app-web-1 | File "/usr/local/lib/python3.12/site-packages/uvicorn/server.py", line 61, in run
fastapi_test_app-web-1 | return asyncio.run(self.serve(sockets=sockets))
fastapi_test_app-web-1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
fastapi_test_app-web-1 | File "/usr/local/lib/python3.12/asyncio/runners.py", line 194, in run
fastapi_test_app-web-1 | return runner.run(main)
fastapi_test_app-web-1 | ^^^^^^^^^^^^^^^^
fastapi_test_app-web-1 | File "/usr/local/lib/python3.12/asyncio/runners.py", line 118, in run
fastapi_test_app-web-1 | return self._loop.run_until_complete(task)
fastapi_test_app-web-1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
fastapi_test_app-web-1 | File "/usr/local/lib/python3.12/asyncio/base_events.py", line 664, in run_until_complete
fastapi_test_app-web-1 | return future.result()
fastapi_test_app-web-1 | ^^^^^^^^^^^^^^^
fastapi_test_app-web-1 | File "/usr/local/lib/python3.12/site-packages/uvicorn/server.py", line 68, in serve
fastapi_test_app-web-1 | config.load()
fastapi_test_app-web-1 | File "/usr/local/lib/python3.12/site-packages/uvicorn/config.py", line 467, in load
fastapi_test_app-web-1 | self.loaded_app = import_from_string(self.app)
fastapi_test_app-web-1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
fastapi_test_app-web-1 | File "/usr/local/lib/python3.12/site-packages/uvicorn/importer.py", line 21, in import_from_string
fastapi_test_app-web-1 | module = importlib.import_module(module_str)
fastapi_test_app-web-1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
fastapi_test_app-web-1 | File "/usr/local/lib/python3.12/importlib/__init__.py", line 90, in import_module
fastapi_test_app-web-1 | return _bootstrap._gcd_import(name[level:], package, level)
fastapi_test_app-web-1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
fastapi_test_app-web-1 | File "<frozen importlib._bootstrap>", line 1381, in _gcd_import
fastapi_test_app-web-1 | File "<frozen importlib._bootstrap>", line 1354, in _find_and_load
fastapi_test_app-web-1 | File "<frozen importlib._bootstrap>", line 1325, in _find_and_load_unlocked
fastapi_test_app-web-1 | File "<frozen importlib._bootstrap>", line 929, in _load_unlocked
fastapi_test_app-web-1 | File "<frozen importlib._bootstrap_external>", line 994, in exec_module
fastapi_test_app-web-1 | File "<frozen importlib._bootstrap>", line 488, in _call_with_frames_removed
fastapi_test_app-web-1 | File "/usr/src/app/app/main.py", line 38, in <module>
fastapi_test_app-web-1 | class HeroOut(Hero):
fastapi_test_app-web-1 | File "/usr/local/lib/python3.12/site-packages/sqlmodel/main.py", line 451, in __new__
fastapi_test_app-web-1 | new_cls = super().__new__(cls, name, bases, dict_used, **config_kwargs)
fastapi_test_app-web-1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
fastapi_test_app-web-1 | File "/usr/local/lib/python3.12/site-packages/pydantic/_internal/_model_construction.py", line 182, in __new__
fastapi_test_app-web-1 | complete_model_class(
fastapi_test_app-web-1 | File "/usr/local/lib/python3.12/site-packages/pydantic/_internal/_model_construction.py", line 491, in complete_model_class
fastapi_test_app-web-1 | schema = cls.__get_pydantic_core_schema__(cls, handler)
fastapi_test_app-web-1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
fastapi_test_app-web-1 | File "/usr/local/lib/python3.12/site-packages/pydantic/main.py", line 578, in __get_pydantic_core_schema__
fastapi_test_app-web-1 | return __handler(__source)
fastapi_test_app-web-1 | ^^^^^^^^^^^^^^^^^^^
fastapi_test_app-web-1 | File "/usr/local/lib/python3.12/site-packages/pydantic/_internal/_schema_generation_shared.py", line 82, in __call__
fastapi_test_app-web-1 | schema = self._handler(__source_type)
fastapi_test_app-web-1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
fastapi_test_app-web-1 | File "/usr/local/lib/python3.12/site-packages/pydantic/_internal/_generate_schema.py", line 468, in generate_schema
fastapi_test_app-web-1 | schema = self._generate_schema(obj)
fastapi_test_app-web-1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^
fastapi_test_app-web-1 | File "/usr/local/lib/python3.12/site-packages/pydantic/_internal/_generate_schema.py", line 700, in _generate_schema
fastapi_test_app-web-1 | schema = self._post_process_generated_schema(self._generate_schema_inner(obj))
fastapi_test_app-web-1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
fastapi_test_app-web-1 | File "/usr/local/lib/python3.12/site-packages/pydantic/_internal/_generate_schema.py", line 722, in _generate_schema_inner
fastapi_test_app-web-1 | return self._model_schema(obj)
fastapi_test_app-web-1 | ^^^^^^^^^^^^^^^^^^^^^^^
fastapi_test_app-web-1 | File "/usr/local/lib/python3.12/site-packages/pydantic/_internal/_generate_schema.py", line 541, in _model_schema
fastapi_test_app-web-1 | {k: self._generate_md_field_schema(k, v, decorators) for k, v in fields.items()},
fastapi_test_app-web-1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
fastapi_test_app-web-1 | File "/usr/local/lib/python3.12/site-packages/pydantic/_internal/_generate_schema.py", line 886, in _generate_md_field_schema
fastapi_test_app-web-1 | common_field = self._common_field_schema(name, field_info, decorators)
fastapi_test_app-web-1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
fastapi_test_app-web-1 | File "/usr/local/lib/python3.12/site-packages/pydantic/_internal/_generate_schema.py", line 951, in _common_field_schema
fastapi_test_app-web-1 | schema = self._apply_annotations(
fastapi_test_app-web-1 | ^^^^^^^^^^^^^^^^^^^^^^^^
fastapi_test_app-web-1 | File "/usr/local/lib/python3.12/site-packages/pydantic/_internal/_generate_schema.py", line 1654, in _apply_annotations
fastapi_test_app-web-1 | schema = get_inner_schema(source_type)
fastapi_test_app-web-1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
fastapi_test_app-web-1 | File "/usr/local/lib/python3.12/site-packages/pydantic/_internal/_schema_generation_shared.py", line 82, in __call__
fastapi_test_app-web-1 | schema = self._handler(__source_type)
fastapi_test_app-web-1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
fastapi_test_app-web-1 | File "/usr/local/lib/python3.12/site-packages/pydantic/_internal/_generate_schema.py", line 1635, in inner_handler
fastapi_test_app-web-1 | schema = self._generate_schema(obj)
fastapi_test_app-web-1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^
fastapi_test_app-web-1 | File "/usr/local/lib/python3.12/site-packages/pydantic/_internal/_generate_schema.py", line 700, in _generate_schema
fastapi_test_app-web-1 | schema = self._post_process_generated_schema(self._generate_schema_inner(obj))
fastapi_test_app-web-1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
fastapi_test_app-web-1 | File "/usr/local/lib/python3.12/site-packages/pydantic/_internal/_generate_schema.py", line 727, in _generate_schema_inner
fastapi_test_app-web-1 | return self.match_type(obj)
fastapi_test_app-web-1 | ^^^^^^^^^^^^^^^^^^^^
fastapi_test_app-web-1 | File "/usr/local/lib/python3.12/site-packages/pydantic/_internal/_generate_schema.py", line 810, in match_type
fastapi_test_app-web-1 | return self._match_generic_type(obj, origin)
fastapi_test_app-web-1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
fastapi_test_app-web-1 | File "/usr/local/lib/python3.12/site-packages/pydantic/_internal/_generate_schema.py", line 858, in _match_generic_type
fastapi_test_app-web-1 | return self._unknown_type_schema(obj)
fastapi_test_app-web-1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
fastapi_test_app-web-1 | File "/usr/local/lib/python3.12/site-packages/pydantic/_internal/_generate_schema.py", line 366, in _unknown_type_schema
fastapi_test_app-web-1 | raise PydanticSchemaGenerationError(
fastapi_test_app-web-1 | pydantic.errors.PydanticSchemaGenerationError: Unable to generate pydantic-core schema for sqlalchemy.orm.base.Mapped[typing.List[app.main.Team]]. Set `arbitrary_types_allowed=True` in the model_config to ignore this error or implement `__get_pydantic_core_schema__` on your type to fully support it.
fastapi_test_app-web-1 |
fastapi_test_app-web-1 |
fastapi_test_app-web-1 | If you got this error by calling handler(<some type>) within `__get_pydantic_core_schema__` then you likely need to call `handler.generate_schema(<some type>)` since we do not call `__get_pydantic_core_schema__` on `<some type>` otherwise to avoid infinite recursion.
fastapi_test_app-web-1 |
fastapi_test_app-web-1 |
fastapi_test_app-web-1 | For further information visit https://errors.pydantic.dev/2.5/u/schema-for-unknown-type\
How can we fix it, such that we can work with HeroOut
?
Solution
According to the documentation of SQLModel you should
only inherit from data models, don't inherit from table models.
But your HeroOut
is inherited from table model (table=True).
Try creating HeroBase
model and inherit from it, as it's shown in the article.
https://sqlmodel.tiangolo.com/tutorial/fastapi/multiple-models/#only-inherit-from-data-models
Answered By - Yurii Motov
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.