Last active
December 25, 2020 00:42
-
-
Save digitalkaoz/fb90c30404ad89bb3764925a653dcc6d to your computer and use it in GitHub Desktop.
SQL Alchemy Many To Many Relation delete cascading
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # domain model | |
| class Company(base): | |
| id: int = Column(BigInteger, primary_key=True, autoincrement=True) | |
| addresses = relationship("CompanyAddress", backref=backref("company",cascade='all,delete-orphan')) | |
| class User(base): | |
| id: int = Column(BigInteger, primary_key=True, autoincrement=True) | |
| addresses = relationship("UserAddress", backref=backref("user",cascade='all,delete-orphan')) | |
| class Address(base): | |
| id: int = Column(BigInteger, primary_key=True, autoincrement=True) | |
| street: str = Column(String(255)) | |
| zipcode: str = Column(String(10)) | |
| city: str = Column(String(255)) | |
| class CompanyAddress(base): | |
| address_id = Column(BigInteger, ForeignKey(Address.id), primary_key=True) | |
| company_id = Column(BigInteger, ForeignKey(Company.id), primary_key=True) | |
| primary: bool = Column(Boolean, comment="primary address") | |
| address = relationship(Address) | |
| class UserAddress(base): | |
| address_id = Column(BigInteger, ForeignKey(Address.id), primary_key=True) | |
| user_id = Column(BigInteger, ForeignKey(User.id), primary_key=True) | |
| primary: bool = Column(Boolean, comment="primary address") | |
| address = relationship(Address) | |
| # data setup | |
| a1 = Address(zipcode="22305", city="Hamburg") # id: 1 | |
| a2 = Address(zipcode="88998", city="Munich") # id: 2 | |
| c = Company() # id: 100 | |
| c.addresses.append(CompanyAddress(address=a1)) | |
| u = User() # id: 1000 | |
| u.addresses.append(UserAddress(address=a1)) | |
| u.addresses.append(UserAddress(address=a2)) | |
| #saving works, all addresses are attached correctly | |
| # delete relation | |
| u.addresses = [a1] | |
| # sqlalchemy tries to insert a new address with the same id (1) and fails bc it still exists | |
| # i want to break up the relation between User and Address but dont want to delete the address itself |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Well if you want to reassign a new collection, you should do
u.addresses = [ua1]instead ofu.addresses = [a1].a1is an instance ofAddress, notUserAddress.And yes if you have declared
cascade="delete-orphan"onUser.address,ua2will be removed from the db table automatically. BTW, cascade should be configured on the "one" side of the one-to-many relationship. Including it in thebackreffunction is incorrect. Instead of:You should do:
A slightly modified version of your snippet that should run as-is (
BigIntegerof sqlite will not auto-increment hence the change):It will create a local sqlite db
company.dbthat you can inspect and play around with.