简体   繁体   English

删除sqlalchemy中的多对多辅助表关联中的所有关联

[英]Delete all in a Many to Many secondary table association in sqlalchemy

I have following models and associations: 我有以下模型和协会:

class CartProductsAssociation(db.Model):
    __tablename__ = 'cart_products_association'
    cart_id = db.Column(db.Integer, db.ForeignKey('carts.id',ondelete='CASCADE'),primary_key=True)
    product_id = db.Column(db.Integer, db.ForeignKey('products.id',ondelete='CASCADE'), primary_key=True)
    quantity = db.Column(db.Integer)

    product = db.relationship("Product", backref="cart_associations", cascade="all,delete",passive_deletes=True)
    cart = db.relationship("Cart", backref="product_associations",cascade="all,delete",passive_deletes=True)


class Product(db.Model):
    __tablename__ = 'products'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String)
    img_path = db.Column(db.String)

    price = db.Column(db.Float, default=0.0)

    product_categories = db.relationship(
        "ProductCategory",
        secondary=product_product_categories,
        back_populates="products")

    carts = db.relationship("Product", secondary="cart_products_association",passive_deletes=True,cascade="all,delete" )

class Cart(db.Model):
    __tablename__ = 'carts'
    id = db.Column(db.Integer, primary_key=True)

    branch_id = db.Column(db.Integer, db.ForeignKey('branch.id'))
    branch = db.relationship("Branch", back_populates="carts")

    page_id = db.Column(db.Integer, db.ForeignKey('pages.id'))
    page = db.relationship("Page", back_populates="carts")


    shopper_id = db.Column(db.String, db.ForeignKey('shoppers.fb_user_id'))
    shopper = db.relationship(
        "Shopper",
        back_populates="carts")

    products = db.relationship("Product", secondary="cart_products_association")
    cart_status = db.Column(db.Enum('user_unconfirmed','user_confirmed','client_unconfirmed','client_confirmed', name='cart_status'), default='user_unconfirmed')

When I am trying to delete a product I am getting following error: AssertionError 当我尝试删除产品时,我收到以下错误:AssertionError

AssertionError: Dependency rule tried to blank-out primary key column 'cart_products_association.cart_id' on instance '<CartProductsAssociation at 0x7f5fd41721d0>'

How can I solve it? 我该如何解决?

it solved the problem: 它解决了这个问题:

 product = models.Product.query.get(product_id)

 for ass in product.cart_associations:

    db.session.delete(ass)

db.session.delete(product)
db.session.commit()

The error is caused by back references cart_associations and product_associations created by CartProductsAssociation . 该错误是由CartProductsAssociation创建的后向引用cart_associationsproduct_associations CartProductsAssociation Since they don't have explicit cascades set, they have the default save-update, merge , and without delete the 由于它们没有明确的级联设置,因此它们具有默认的save-update, merge和不delete

default behavior is to instead de-associate ... by setting their foreign key reference to NULL. 默认行为是通过将其外键引用设置为NULL来取消关联。

Due to this when a Product is up for deletion SQLAlchemy will first fetch the related CartProductsAssociation objects and try to set the primary key to NULL. 因此,当Product被删除时,SQLAlchemy将首先获取相关的CartProductsAssociation对象并尝试将主键设置为NULL。

It seems that originally there has been an attempt to use passive_deletes=True with ondelete='CASCADE' , but the passive deletes have ended up on the wrong side of the relationship pair. 似乎最初尝试使用passive_deletes=Trueondelete='CASCADE' ,但被动删除最终在关系对的错误一侧。 This should produce a warning: 这应该产生一个警告:

sqlalchemy/orm/relationships.py:1790: SAWarning: On CartProductsAssociation.product, 'passive_deletes' is normally configured on one-to-many, one-to-one, many-to-many relationships only.

If the relationships are configured as 如果关系配置为

class CartProductsAssociation(db.Model):
    ...
    product = db.relationship(
        "Product", backref=db.backref("cart_associations",
                                      cascade="all",
                                      passive_deletes=True))
    cart = db.relationship(
        "Cart", backref=db.backref("product_associations",
                                   cascade="all",
                                   passive_deletes=True))

instead, then when a Product instance that has not loaded its related CartProductsAssociation objects is deleted, SQLAlchemy will let the DB handle cascading. 相反,当删除加载其相关CartProductsAssociation对象的Product实例时,SQLAlchemy将让DB处理级联。 Note that the SQLAlchemy delete cascade is also necessary, or the error will come back if a Product instance that has loaded its related association objects is deleted. 请注意,SQLAlchemy delete级联也是必需的,否则如果删除加载其相关关联对象的Product实例,则会返回错误。 passive_deletes="all" can also be used, if there are some special triggers or such in place in the DB that must be allowed to fire. 如果在DB中有一些必须允许触发的特殊触发器或类似触发器,也可以使用passive_deletes="all"

When deleting a Product that has loaded both carts and cart_associations the situation is even more complicated, because both association object pattern and a many to many relationship are in use, and the 2 relationships do not coordinate changes together – see the warning in "Association Object" . 当删除Product已加载两个推车cart_associations的情况更复杂,因为两者的关联对象模式和多对多的关系都在使用,和2间的关系并不协调变更在一起-看到警告“关联对象“ You might want to consider either making the other relationship viewonly , or use the association proxy extension across the association object relationship: 你可能要考虑做任何其他关系viewonly ,或使用协会代理跨越关联对象关系扩展:

class Product:
    ...
    carts = association_proxy(
        'cart_associations', 'cart',
        creator=lambda cart: CartProductsAssociation(cart=cart))

Finally, the delete cascade in Product.carts is a bit odd, though may be as designed, and will delete the related Cart objects along with the Product if they have been loaded, and additionally removes rows from the secondary table. 最后, Product.cartsdelete级联有点奇怪,虽然可能是设计的,如果已经加载了将删除相关的Cart对象以及Product ,并且还从辅助表中删除行。 On the other hand that relationship has passive deletes also, so the Cart objects are not deleted if not loaded when the Product is deleted, which would seem to conflict with the SQLAlchemy cascade. 另一方面,该关系也具有被动删除,因此如果在删除Product时未加载Cart对象,则不会删除Cart对象,这似乎与SQLAlchemy级联冲突。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何从SQLAlchemy中的多对多(二级)表中删除记录? - How to delete records from many-to-many (secondary) table in SQLAlchemy? SQLAlchemy - 使用关联表查询多对多 - SQLAlchemy - Query Many to Many with association table SQLAlchemy 警告与关联表的多对多关系 - SQLAlchemy warning for many to many relation with association table 多对多关联表上的SQLAlchemy关系 - SQLAlchemy relationship on many-to-many association table Flask-SQLAlchemy:如何使用用户 ID 从多对多辅助表中删除行 - Flask-SQLAlchemy: How to delete row from many-to-many secondary table with the user id SQLAlchemy尝试两次删除多对多的次要关系 - SQLAlchemy Attempting to Twice Delete Many to Many Secondary Relationship 在SQLAlchemy多对多关联表中存储对其他行的引用 - Storing reference to other rows in SQLAlchemy Many-to-Many association table SQLAlchemy使用关联表以多对多关系插入数据 - SQLAlchemy Inserting Data in a Many-to-Many Relationship with Association Table Sqlalchemy:template_id和部门之间多对多关系的关联表。 如何删除关系? - Sqlalchemy : association table for many-to-many relationship between template_id and department. How can I delete a relationship? 多对多关联对象和定义的所有关系在删除时崩溃 - Many-to-Many with association object and all relationships defined crashes on delete
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM