Unable to use original type hint by defining relationship
First Check
- [X] I added a very descriptive title to this issue.
- [X] I used the GitHub search to find a similar issue and didn't find it.
- [X] I searched the SQLModel documentation, with the integrated search.
- [X] I already searched in Google "How to X in SQLModel" and didn't find any information.
- [X] I already read and followed all the tutorial in the docs and didn't find an answer.
- [X] I already checked if it is not related to SQLModel but to Pydantic.
- [X] I already checked if it is not related to SQLModel but to SQLAlchemy.
Commit to Help
- [X] I commit to help with one of those options 👆
Example Code
from typing import Optional
from sqlmodel import Field, SQLModel, Relationship, create_engine, Session
class Team(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
name: str = Field(index=True)
headquarters: str
# key sentence
heroes: list["Hero"] = Relationship(back_populates='team')
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)
team_id: Optional[int] = Field(default=None, foreign_key=Team.id)
database_url = f'mysql+mysqlconnector://{user}:{password}@{host}/{database_name}'
engine = create_engine(database_url, encoding='utf8', echo=True)
if __name__ == '__main__':
SQLModel.metadata.create_all(engine)
Description
I create Hero and Team models and try to use python original type hint, but while running it, it occurs exceptions...
Traceback (most recent call last): File "pydantic\validators.py", line 709, in pydantic.validators.find_validators TypeError: issubclass() arg 1 must be a class
Traceback (most recent call last):
File "C:\Users\10620\Desktop\Code\Python\sqlmodel\table_relationship.py", line 5, in
class Team(SQLModel, table=True):
File "C:\Users\10620\AppData\Local\Programs\Python\Python310\lib\site-packages\sqlmodel\main.py", line 342, in init
temp_field = ModelField.infer(
File "pydantic\fields.py", line 488, in pydantic.fields.ModelField.infer
File "pydantic\fields.py", line 419, in pydantic.fields.ModelField.init
File "pydantic\fields.py", line 534, in pydantic.fields.ModelField.prepare
File "pydantic\fields.py", line 728, in pydantic.fields.ModelField._type_analysis
File "pydantic\fields.py", line 778, in pydantic.fields.ModelField._create_sub_type
File "pydantic\fields.py", line 419, in pydantic.fields.ModelField.init
File "pydantic\fields.py", line 539, in pydantic.fields.ModelField.prepare
File "pydantic\fields.py", line 801, in pydantic.fields.ModelField.populate_validators
File "pydantic\validators.py", line 718, in find_validators
RuntimeError: error checking inheritance of 'Hero' (type: str)
The solution is adding List from typing and replacing it, but I don't know how to solve this bug...
link: https://sqlmodel.tiangolo.com/tutorial/relationship-attributes/define-relationships-attributes/
Operating System
Windows
Operating System Details
No response
SQLModel Version
0.0.6
Python Version
3.10.1
Additional Context
No response
I am not sure I understand your question correctly, but here list["Hero"] should indeed be List["Hero"]. From Python 3.9 onwards, generic list[Hero] should work as well, I think, but that requires your code to be rearranged, so that Hero is defined before Team.
@Whitroom pls update to pydantic v1.9.1 - it should be fixed
I meet a similar problem,
class Base(SQLModel):
pass
class Test:
basemodel = Base # type alias at here, classVar[type[Base]] also didn't work
__slots__ = 'filename', 'datamodel'
def __init__(self, filename: str, datamodel: Optional[Base] = None, **kwargs):
self.filename = filename
if datamodel is not None:
assert isinstance(datamodel, self.basemodel) # self.basemodel is Any at here, should be type[Base]
self.datamodel = datamodel
else:
self.datamodel = self.basemodel(**kwargs) # self.basemodel is Any at here, should be type[Base]
If you remove inheritance of Base, typehint work perfectly. My stupid solution is adding a classmethod to get instance of Base,
class Base(SQLModel, table=True):
@classmethod
def get_instance(cls, data: dict):
return Base(**data)
class Test:
basemodel = Base.get_instance
__slots__ = 'filename', 'datamodel'
def __init__(self, filename: str, datamodel: Optional[Base] = None, **kwargs):
self.filename = filename
if datamodel is not None:
assert isinstance(datamodel, self.basemodel)
self.datamodel = datamodel
else:
self.datamodel = self.basemodel(**kwargs)
Btw, filename is private attribute of Base at first, but idk how to init it.