marshmallow-sqlalchemy icon indicating copy to clipboard operation
marshmallow-sqlalchemy copied to clipboard

Issue with primary keys that are also foreign keys

Open elemoine opened this issue 6 years ago • 2 comments

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.

elemoine avatar Aug 05 '19 15:08 elemoine

Bump

jonbulica99 avatar Apr 06 '20 08:04 jonbulica99

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"}}

torotil avatar Jul 08 '22 09:07 torotil