'Deleting object in a (SQLAlchemy) many-to-many relationship (works in sqlite but fails when using postgres)?
I seem to hit an issue when trying to delete an object from a many-to-many relation that seems to work with sqlite, but fails on postgres.
Any help or hint is highly appreciated!
This part is the code fails when using postgres.
# try to delete group 1
session.query(Group).filter_by(name="group 1").delete()
Example code:
Many to many example:
An Item can belong to many groups and a Group can contain many items
Is it possible to delete a group containing a number of items without
a need to set the Group.items collection to [] and still keep all the items?
from sqlalchemy import Column, Integer, String, Table, ForeignKey, create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, relationship
from testcontainers.postgres import PostgresContainer
Base = declarative_base()
item_group_members = Table('item_group_members', Base.metadata,
Column('group_id', ForeignKey('group.id'), primary_key=True),
Column('item_id', ForeignKey('item.id'), primary_key=True)
)
class Group(Base):
__tablename__ = 'group'
id = Column(Integer, primary_key=True, index=True)
name = Column(String, unique=True, nullable=False)
# relationships
items = relationship("Item", secondary=item_group_members, back_populates="groups")
class Item(Base):
__tablename__ = 'item'
id = Column(Integer, primary_key=True, index=True)
name = Column(String, unique=False, nullable=False)
# relationships
groups = relationship("Group", secondary=item_group_members, back_populates="items")
def run(connection_url):
engine = create_engine(connection_url)
Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine)
session = Session()
# create some groups
group1 = Group(name="group 1")
group2 = Group(name="group 2")
# create some items
item1 = Item(name="Item 1")
item2 = Item(name="item 2")
item3 = Item(name="Item 1")
# add some items to a group
group1.items = [item1, item2, item3]
group2.items = [item2, item3]
# add all to the session and commit
session.add_all([group1, group2, item1, item2, item3])
session.commit()
# try to delete group 1
# FAILS when using Postgres!!!
session.query(Group).filter_by(name="group 1").delete()
assert session.query(Item).count() == 3
assert session.query(Group).count() == 1
def run_sqlite():
run('sqlite://')
def run_postgres():
with PostgresContainer("postgres:latest") as postgres:
run(postgres.get_connection_url())
if __name__ == '__main__':
run_sqlite() # works
run_postgres() # fails with an error message
sqlite works, but postgres does not. It results in an error:
sqlalchemy.exc.IntegrityError: (psycopg2.errors.ForeignKeyViolation) update or delete on table "group" violates foreign key constraint "item_group_members_group_id_fkey" on table "item_group_members"
DETAIL: Key (id)=(1) is still referenced from table "item_group_members".```
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
