sad*_*605 5 python sqlalchemy flask flask-sqlalchemy
我有以下模型和关联:
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')
Run Code Online (Sandbox Code Playgroud)
当我尝试删除产品时出现以下错误:AssertionError
AssertionError: Dependency rule tried to blank-out primary key column 'cart_products_association.cart_id' on instance '<CartProductsAssociation at 0x7f5fd41721d0>'
Run Code Online (Sandbox Code Playgroud)
我该如何解决?
它解决了问题:
product = models.Product.query.get(product_id)
for ass in product.cart_associations:
db.session.delete(ass)
db.session.delete(product)
db.session.commit()
Run Code Online (Sandbox Code Playgroud)
该错误是由创建的反向引用cart_associations和Product_associationsCartProductsAssociation
引起的。由于它们没有设置显式级联,因此它们具有默认值,save-update, merge
并且没有delete
\n\n\n默认行为是通过将外键引用设置为 NULL 来取消关联...。
\n
因此,当Product
要删除 a 时,SQLAlchemy 将首先获取相关CartProductsAssociation
对象并尝试将主键设置为 NULL。
看来最初曾尝试使用passive_deletes=True
with ondelete=\'CASCADE\'
,但被动删除最终出现在关系对的错误一侧。这应该会产生一个警告:
\n\n\n\n
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.
如果关系配置为
\n\nclass CartProductsAssociation(db.Model):\n ...\n product = db.relationship(\n "Product", backref=db.backref("cart_associations",\n cascade="all",\n passive_deletes=True))\n cart = db.relationship(\n "Cart", backref=db.backref("product_associations",\n cascade="all",\n passive_deletes=True))\n
Run Code Online (Sandbox Code Playgroud)\n\n相反,当删除未加载其相关对象的Product
实例时,SQLAlchemy 将让 DB 处理级联。注意,SQLAlchemy级联也是必要的,否则如果删除了加载了相关关联对象的实例,则会返回错误。如果数据库中存在一些特殊触发器或必须允许触发的此类触发器,也可以使用。CartProductsAssociation
delete
Product
passive_deletes="all"
Product
当删除同时加载了carts和cart_associations的 a 时,情况会更加复杂,因为关联对象模式和多对多关系都在使用中,并且这 2 个关系不会一起协调更改 \xe2\x80\x93 请参阅警告在“关联对象”中。您可能需要考虑将其他关系设置为viewonly ,或者在关联对象关系中使用关联代理扩展:
class Product:\n ...\n carts = association_proxy(\n \'cart_associations\', \'cart\',\n creator=lambda cart: CartProductsAssociation(cart=cart))\n
Run Code Online (Sandbox Code Playgroud)\n\n最后,delete
级联Product.carts
有点奇怪,尽管可能是按照设计的,并且将删除相关Cart
对象以及Product
它们是否已加载,并且另外从辅助表中删除行。另一方面,该关系也具有被动删除,因此如果在删除时未加载Cart
对象,则不会Product
删除对象,这似乎与 SQLAlchemy 级联冲突。
归档时间: |
|
查看次数: |
3620 次 |
最近记录: |