Adding _init_private_attributes to SQLModel __init__ function.#472
Adding _init_private_attributes to SQLModel __init__ function.#472alexisgaziello wants to merge 2 commits intofastapi:mainfrom
Conversation
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
|
Thanks for the fix! I've used it as a workaround in my project by adding it to the init method of my own model. I noticed that when I loaded a model from the database the private attributes were not initialized because the init in SQLModel is not called. I had to call it separately on the model before being able to use the private attribute. Have you tested whether your fix works when loading a model from the database? |
Do you mean in an example such as the one below? test_id = uuid4()
class Hero(SQLModel, table=True):
id: UUID = Field(default_factory=uuid4, primary_key=True)
_private_hero_attribute: str = PrivateAttr(default="private hero value")
metadata = MetaData()
with Session(engine) as session:
hero_rusty_man = Hero(
id=test_id,
)
session.add(hero_rusty_man)
session.commit()
with Session(engine) as session:
statement = select(Hero).where(Hero.id == test_id)
hero = session.exec(statement).scalars().first()
assert hero._private_hero_attribute == "private hero value" # this fails
hero = Hero.from_orm(hero)
assert hero._private_hero_attribute == "private hero value" # this doesn't failIndeed, when running SQLAlchemy, the private attributes don't get correctly initialized. I haven't figured out if there is a way to "automate" this process. Maybe SQLAlchemy is using another init/factory_function? |
|
📝 Docs preview for commit 844e21c at: https://639ce0b204318b01e2823f64--sqlmodel.netlify.app |
|
Whats the status of this? |
|
Any chance we can get this merged? |
|
@lucas-labs the reality is that the fix doesn't fully work, as shown in #472 (comment) |
This is the way this works in Pydantic; the method is called from I imagine this is the case for many users since a model that represents a database object might need to have more often attributes that do not necessary link to the database itself and are used for internal logic. |
|
I think I am also running into this issue. I am retrieving an object from the database and want to copy it like described in the fastapi docs for partial updates. object_from_db = session.exec(select_cmd).one_or_none()
copied_object = object_from_db.model_copy() The model_copy results in the following error: Is there a workaround I can use? |
|
Maybe it will help someone. If I need to use an attribute that will not be linked to the database, I use attributes with double double underscores. class Hero(SQLModel, table=True):
id: int = Field(primary_key=True)
name: str = Field(...)
__private_hero_attribute__: str = "private hero value"They work, but there is no validation applied to them. |
|
Ping, this is still needed ! |
|
@alexisgaziello, thanks for your efforts! Do you have any plans to continue working on this? |
|
This pull request has a merge conflict that needs to be resolved. |
|
As this PR has been waiting for the original user for a while but seems to be inactive, it's now going to be closed. But if there's anyone interested, feel free to create a new PR. |
Fixing:
Private attributes cannot be used in SQLModel. Attributes initialized with
PrivateAttrcannot be found.Proposed solution:
Add a missing line from Pydantic source code.
Note: the class method from_orm does have this initialization.
Related issues:
#149 mentions this issue
Disclaimer
This is my first-ever contribution to an open-source project. I would appreciate any kind of feedback.