Equality SQLModels #761
Replies: 5 comments 2 replies
-
+1 here, I think the issue is related to the object fetched from queries aren't properly initialized Pydantic object, more specifically here One thing I tried is to do to confirm this is have |
Beta Was this translation helpful? Give feedback.
-
This is definitely a bug, here's a simple example that reproduces it: from sqlmodel import Field, Session, SQLModel, create_engine
class Bug(SQLModel, table=True):
__tablename__ = "bugs"
code: str = Field(primary_key=True)
engine = create_engine("sqlite://")
SQLModel.metadata.create_all(engine)
bug_code = "pydantic-private"
with Session(engine) as session:
session.add(Bug(code=bug_code))
session.commit()
bug_1 = session.get(Bug, bug_code)
bug_2 = session.get(Bug, bug_code)
print(f"{bug_1 == bug_2=}")
#> AttributeError: 'Bug' object has no attribute '__pydantic_private__'. Did you mean: '__pydantic_complete__'? |
Beta Was this translation helpful? Give feedback.
-
This works for me: from typing import Any, Optional
from pydantic import BaseModel
from sqlmodel import SQLModel, Field
def __eq__(self, other: Any) -> bool:
if isinstance(other, BaseModel):
# When comparing instances of generic types for equality, as long as all field values are equal,
# only require their generic origin types to be equal, rather than exact type equality.
# This prevents headaches like MyGeneric(x=1) != MyGeneric[Any](x=1).
self_type = self.__pydantic_generic_metadata__['origin'] or self.__class__
other_type = other.__pydantic_generic_metadata__['origin'] or other.__class__
dict1 = self.__dict__
dict2 = other.__dict__
if '_sa_instance_state' in dict1:
dict1.pop('_sa_instance_state')
if '_sa_instance_state' in dict2:
dict2.pop('_sa_instance_state')
return (
self_type == other_type
and dict1 == dict2
)
# and self.__pydantic_private__ == other.__pydantic_private__
# and self.__pydantic_extra__ == other.__pydantic_extra__
else:
return NotImplemented # delegate to the other item in the comparison
SQLModel.__eq__ = __eq__ |
Beta Was this translation helpful? Give feedback.
-
More broadly, this problem has consequences outside of equality scenarios. We have run into this issue when attempting to On simple objects without any nested back references simply dumping and destructuring the dumped object back into the constructor works as @KnightArthurRen points out ( One solution, though I have no idea about the validity of this method, is to explicitly set both
This works for our use case because we are not utilizing either of those fields, but this feels not good. |
Beta Was this translation helpful? Give feedback.
-
I came across the issue in SQLModel 0.0.14, but the issue seems to be solved by 0.0.16 (current latest), likely by this PR: #807 |
Beta Was this translation helpful? Give feedback.
-
First Check
Commit to Help
Example Code
Description
When I manipulate with sqlalchemy:
sqlalchemy change value
_sa_instance_state
in modelAnd when I check on equal it call pydantic
__eq__()
Here are
self.__dict__
andother.__dict__
contain different key_sa_instance_state
, or if Model does not manipulate with SqlAlchemy this field may no exist.Also I'm not sure about the
__pydantic_private__
and__pydantic_extra__
.I think SQLModel need self method
__eq__
Operating System
macOS
Operating System Details
No response
SQLModel Version
0.0.14
Python Version
Python 3.9.6
Additional Context
No response
Beta Was this translation helpful? Give feedback.
All reactions