我有以下模特和协会:
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')
当我尝试删除某个产品时,我收到以下错误消息: 的AssertionError
AssertionError: Dependency rule tried to blank-out primary key column 'cart_products_association.cart_id' on instance '<CartProductsAssociation at 0x7f5fd41721d0>'
我该如何解决?
答案 0 :(得分:2)
它解决了这个问题:
product = models.Product.query.get(product_id)
for ass in product.cart_associations:
db.session.delete(ass)
db.session.delete(product)
db.session.commit()
答案 1 :(得分:1)
该错误是由CartProductsAssociation
创建的后向引用 cart_associations 和 product_associations 引起的。由于它们没有明确的cascades设置,因此它们具有默认save-update, merge
,而没有delete
默认行为是通过将其外键引用设置为NULL来取消关联....
因此,当Product
被删除时,SQLAlchemy将首先获取相关的CartProductsAssociation
对象,并尝试将主键设置为NULL。
似乎最初尝试将passive_deletes=True
与ondelete='CASCADE'
一起使用,但被动删除最终导致了关系对的错误一面。这应该产生警告:
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.
如果关系配置为
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))
相反,当没有加载其相关Product
对象的CartProductsAssociation
实例被删除时,SQLAlchemy将让DB处理级联。请注意,SQLAlchemy delete
级联也是必需的,否则如果已加载其相关关联对象的Product
实例被删除,则会返回错误。如果在DB中有一些必须允许触发的特殊触发器或类似触发器,也可以使用passive_deletes="all"
。
删除已加载购物车和 cart_associations 的Product
时,情况会更复杂,因为association object模式和{ {3}}关系正在使用中,并且两个关系不会一起协调更改 - 请参阅many to many中的警告。您可能想要考虑建立其他关系"Association Object",或者在关联对象关系中使用viewonly扩展名:
class Product:
...
carts = association_proxy(
'cart_associations', 'cart',
creator=lambda cart: CartProductsAssociation(cart=cart))
最后,delete
中的Product.carts
级联有点奇怪,但可能与设计完全相同,并会删除相关的Cart
个对象以及Product
已加载,并另外从辅助表中删除行。另一方面,该关系也具有被动删除功能,因此如果在删除Cart
时未加载Product
对象,则