I used the GitHub search to find a similar issue and didn't find it.
I searched the SQLModel documentation, with the integrated search.
I already searched in Google "How to X in SQLModel" and didn't find any information.
I already read and followed all the tutorial in the docs and didn't find an answer.
I already checked if it is not related to SQLModel but to Pydantic.
I already checked if it is not related to SQLModel but to SQLAlchemy.
Commit to Help
I commit to help with one of those options 👆
Example Code
fromsqlmodelimportRelationship, SQLModel, Fieldfrompydantic.mainimportBaseModelclassSpecialFieldValidator(BaseModel):
id: int=Field(primary_key=True, index=True)
def__init_subclass__(cls) ->None:
# Try to figure out what type the special_field relation hasprint("special_field"incls.__annotations__) # Falseprint("special_field"incls.__fields__) # Falseprint("special_field"incls.__sqlmodel_relationships__) # True, but no type info via this dict, just a plain RelationshipInfo() instance:print(dict(cls.__sqlmodel_relationships__["special_field"].__dict__)) # {'back_populates': None, 'link_model': None, 'sa_relationship': None, 'sa_relationship_args': None, 'sa_relationship_kwargs': None}returnsuper().__init_subclass__()
classMyModelA(SQLModel, SpecialFieldValidator, table=True):
id: int=Field(primary_key=True)
special_field_id: int=Field(foreign_key="mymodelb.id")
special_field: "MyModelB"=Relationship()
classMyModelB(SQLModel, SpecialFieldValidator, table=True):
id: int=Field(primary_key=True)
special_field_id: int=Field(foreign_key="mymodela.id")
special_field: MyModelA=Relationship()
Description
I'm trying to write a class (SpecialFieldValidator) that is supposed to check whether a specific field, which is always a Relationship, was annotated with a particular type.
However, the actual type annotation seems to be getting erased - looking in fields, annotations yields nothing, and the data in sqlmodel_relationships does not feature a type.
Operating System
Linux
Operating System Details
No response
SQLModel Version
0.0.8
Python Version
3.11.0
Additional Context
SQLAlchemy version is 1.4.41
I found this issue: #255 that seems related, saying SQLAlchemy 1.4.36 breaks relationship, but SQLModels dependencies were officially updated to >=1.4.41 more recently than that so I figured this is a new issue.
I'm also facing this issue. From what I could see, one potential solution could be the following (if support for relationship information as part of the pydantic model is not included as a feature in SQLModel fure releases, so consider this a workaround):
Override the __new__ dunder method ( as __init__ is not used by SQLModel).
Populate the pydantic _model_fields property with missing info from relationships.
Rebuild pydantic model schema to reflect such changes.
In your particular use-case it would be something like the following (behaviour could potentially be abstracted at SQLModel level, or at least at a base class level, so it is not performed in a per-class/per-attribute level each time):
fromsqlmodelimportRelationship, SQLModel, Fieldfrompydantic.mainimportBaseModelclassSpecialFieldValidator(BaseModel):
id: int=Field(primary_key=True, index=True)
def__init_subclass__(cls) ->None:
# Try to figure out what type the special_field relation hasprint("special_field"incls.__annotations__) # Falseprint("special_field"incls.__fields__) # Falseprint("special_field"incls.__sqlmodel_relationships__) # True, but no type info via this dict, just a plain RelationshipInfo() instance:print(dict(cls.__sqlmodel_relationships__["special_field"].__dict__)) # {'back_populates': None, 'link_model': None, 'sa_relationship': None, 'sa_relationship_args': None, 'sa_relationship_kwargs': None}returnsuper().__init_subclass__()
classMyModelA(SQLModel, SpecialFieldValidator, table=True):
id: int=Field(primary_key=True)
special_field_id: int=Field(foreign_key="mymodelb.id")
special_field: "MyModelB"=Relationship()
def__new__(cls, *args: Any, **kwargs: Any) ->Any:
new_object=super().__new__(cls, *args, **kwargs)
new_object.model_fields.update({"special_field": Field(..., description="description of your model property coming from the relationship")})
new_object.model_rebuild(force=True)
returnnew_objectclassMyModelB(SQLModel, SpecialFieldValidator, table=True):
id: int=Field(primary_key=True)
special_field_id: int=Field(foreign_key="mymodela.id")
special_field: MyModelA=Relationship()
def__new__(cls, *args: Any, **kwargs: Any) ->Any:
new_object=super().__new__(cls, *args, **kwargs)
new_object.model_fields.update({"special_field": Field(..., description="description of your model property coming from the relationship")})
new_object.model_rebuild(force=True)
returnnew_object
Activity
jarey commented on Dec 2, 2024
I'm also facing this issue. From what I could see, one potential solution could be the following (if support for relationship information as part of the pydantic model is not included as a feature in SQLModel fure releases, so consider this a workaround):
In your particular use-case it would be something like the following (behaviour could potentially be abstracted at SQLModel level, or at least at a base class level, so it is not performed in a per-class/per-attribute level each time):
Kind regards.
test: add regression tests for issue fastapi#530 - relationship annot…