marshmallow-sqlalchemy
marshmallow-sqlalchemy copied to clipboard
Issue with primary keys that are also foreign keys
I have a case where marshmallow-sqlalchemy causes an SQLAlchemy FlushError at session commit time.
This is the error I get:
sqlalchemy.orm.exc.FlushError: New instance <Parent at 0x7f790f4832b0> with identity key (<class '__main__.Parent'>, (1,), None) conflicts with persistent instance <Parent at 0x7f790f4830f0>
My case is that of a Parent class/table with a primary key that also is a foreign key to a Child class/table.
The code that triggers the error is the following:
parent = Session.query(Parent).one()
json_data = {"child": {"id": 1, "name": "new name"}}
with Session.no_autoflush:
instance = ParentSchema().load(json_data)
Session.add(instance.data)
Session.commit() # -> FlushError
Session.query(Parent).one() loads the parent object from the database and associates it with the session. ParentSchema().load() doesn't load the parent object from the database. Instead it creates a new object. And that new object has the same identity as the parent object that was loaded by Session.query(Parent).one().
I tend to think that the problem is in ModelSchema.get_instance(), which fails to load the instance from the database and return None instead.
This is the full test-case: https://gist.github.com/elemoine/dcd0475acb26cdbf827015c8fae744ba. The code that initially triggered this issue in my application is more complex than this. This test-case is the minimal code reproducing the issue that I've been able to come up with.
Bump
It should work if your JSON would also include the id of the parent model:
json_data = {"id": 1, "child": {"id": 1, "name": "new name"}}