SQLAlchemy尝试两次删除多对多二级关系 [英] SQLAlchemy Attempting to Twice Delete Many to Many Secondary Relationship

查看:121
本文介绍了SQLAlchemy尝试两次删除多对多二级关系的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个product模型,该模型与product_categories有很多关系,如下所述:

I have a product model with a many to many relationship to product_categories as described below:

class Product(Base):
    """ The SQLAlchemy declarative model class for a Product object. """
    __tablename__ = 'products'

    id = Column(Integer, primary_key=True)
    part_number = Column(String(10), nullable=False, unique=True)
    name = Column(String(80), nullable=False, unique=True)
    description = Column(String(2000), nullable=False)
    categories = relationship('Category', secondary=product_categories,
                               backref=backref('categories', lazy='dynamic'))


class Category(Base):
    """ The SQLAlchemy declarative model class for a Category object. """                        
    __tablename__ = 'categories'                                                                 

    id = Column(Integer, primary_key=True)
    lft = Column(Integer, nullable=False)
    rgt = Column(Integer, nullable=False)                                                        
    name = Column(String(80), nullable=False)                                                    
    description = Column(String(2000), nullable=False)                                           
    order = Column(Integer)                                                                      
    products = relationship('Product', secondary=product_categories,
                               backref=backref('products', lazy='dynamic', order_by=name))

product_categories = Table('product_categories', Base.metadata,
    Column('products_id', Integer, ForeignKey('products.id')),
    Column('categories_id', Integer, ForeignKey('categories.id'))
)

然后,我尝试使用以下方法删除该对象:

Then, I'm trying to delete this object with:

product = DBSession.query(Product).filter_by(name = 'Algaecide').one()
DBSession().delete(product)

但是,我得到的是错误消息StaleDataError: DELETE statement on table 'product_categories' expected to delete 1 row(s); Only 0 were matched..如果您注意到,它似乎在两次运行DELETE语句.因此,它第一次成功从product_categories表中删除了product_id,但是由于某种原因又尝试再次执行该操作,然后决定它需要抛出一个异常,因为它不存在.

But, what I get is the error message StaleDataError: DELETE statement on table 'product_categories' expected to delete 1 row(s); Only 0 were matched.. If you notice, it appears to be running the DELETE statement twice. So, the first time it's successfully removes the product_id from the product_categories table, but then attempts to do it yet again for whatever reason, and then decides it needs to throw an exception because it's not there.

>>> Attempting to delete the product 'Algaecide' assigned to categories: [<myproject.models.category.Category object at 0x106fa9d90>]
21:39:50 INFO  [sqlalchemy.engine.base.Engine][Dummy-2] SELECT categories.id AS categories_id, categories.lft AS categories_lft, categories.rgt AS categories_rgt, categories.name AS categories_name, categories.description AS categories_description, categories.`order` AS categories_order
FROM categories, product_categories
WHERE %s = product_categories.products_id AND categories.id = product_categories.categories_id ORDER BY categories.name
21:39:50 INFO  [sqlalchemy.engine.base.Engine][Dummy-2] (109L,)
21:39:50 INFO  [sqlalchemy.engine.base.Engine][Dummy-2] DELETE FROM product_categories WHERE product_categories.products_id = %s AND product_categories.categories_id = %s
21:39:50 INFO  [sqlalchemy.engine.base.Engine][Dummy-2] (109L, 18L)
21:39:50 INFO  [sqlalchemy.engine.base.Engine][Dummy-2] DELETE FROM product_categories WHERE product_categories.products_id = %s AND product_categories.categories_id = %s
21:39:50 INFO  [sqlalchemy.engine.base.Engine][Dummy-2] (109L, 18L)
21:39:50 INFO  [sqlalchemy.engine.base.Engine][Dummy-2] ROLLBACK
21:39:50 ERROR [pyramid_debugtoolbar][Dummy-2] Exception at http://0.0.0.0:6543/product/Algaecide/edit
traceback url: http://0.0.0.0:6543/_debug_toolbar/exception?token=6344937a98ee26992689&tb=4421411920
Traceback (most recent call last):
  File "/Users/derek/pyramid/myproject/lib/python2.7/site-packages/pyramid_debugtoolbar-2.3-py2.7.egg/pyramid_debugtoolbar/toolbar.py", line 178, in toolbar_tween
    response = _handler(request)
  File "/Users/derek/pyramid/myproject/lib/python2.7/site-packages/pyramid_debugtoolbar-2.3-py2.7.egg/pyramid_debugtoolbar/panels/performance.py", line 57, in resource_timer_handler
    result = handler(request)
  File "/Users/derek/pyramid/myproject/lib/python2.7/site-packages/pyramid/tweens.py", line 21, in excview_tween
    response = handler(request)
  File "/Users/derek/pyramid/myproject/lib/python2.7/site-packages/pyramid_tm-0.10-py2.7.egg/pyramid_tm/__init__.py", line 95, in tm_tween
    reraise(*exc_info)
  File "/Users/derek/pyramid/myproject/lib/python2.7/site-packages/pyramid_tm-0.10-py2.7.egg/pyramid_tm/__init__.py", line 83, in tm_tween
    manager.commit()
  File "/Users/derek/pyramid/myproject/lib/python2.7/site-packages/transaction-1.4.3-py2.7.egg/transaction/_manager.py", line 111, in commit
    return self.get().commit()
  File "/Users/derek/pyramid/myproject/lib/python2.7/site-packages/transaction-1.4.3-py2.7.egg/transaction/_transaction.py", line 280, in commit
    reraise(t, v, tb)
  File "/Users/derek/pyramid/myproject/lib/python2.7/site-packages/transaction-1.4.3-py2.7.egg/transaction/_transaction.py", line 271, in commit
    self._commitResources()
  File "/Users/derek/pyramid/myproject/lib/python2.7/site-packages/transaction-1.4.3-py2.7.egg/transaction/_transaction.py", line 417, in _commitResources
    reraise(t, v, tb)
  File "/Users/derek/pyramid/myproject/lib/python2.7/site-packages/transaction-1.4.3-py2.7.egg/transaction/_transaction.py", line 389, in _commitResources
    rm.tpc_begin(self)
  File "/Users/derek/pyramid/myproject/lib/python2.7/site-packages/zope.sqlalchemy-0.7.5-py2.7.egg/zope/sqlalchemy/datamanager.py", line 90, in tpc_begin
    self.session.flush()
  File "/Users/derek/pyramid/myproject/lib/python2.7/site-packages/SQLAlchemy-0.9.8-py2.7-macosx-10.6-intel.egg/sqlalchemy/orm/session.py", line 1919, in flush
    self._flush(objects)
  File "/Users/derek/pyramid/myproject/lib/python2.7/site-packages/SQLAlchemy-0.9.8-py2.7-macosx-10.6-intel.egg/sqlalchemy/orm/session.py", line 2037, in _flush
    transaction.rollback(_capture_exception=True)
  File "/Users/derek/pyramid/myproject/lib/python2.7/site-packages/SQLAlchemy-0.9.8-py2.7-macosx-10.6-intel.egg/sqlalchemy/util/langhelpers.py", line 60, in __exit__
    compat.reraise(exc_type, exc_value, exc_tb)
  File "/Users/derek/pyramid/myproject/lib/python2.7/site-packages/SQLAlchemy-0.9.8-py2.7-macosx-10.6-intel.egg/sqlalchemy/orm/session.py", line 2001, in _flush
    flush_context.execute()
  File "/Users/derek/pyramid/myproject/lib/python2.7/site-packages/SQLAlchemy-0.9.8-py2.7-macosx-10.6-intel.egg/sqlalchemy/orm/unitofwork.py", line 372, in execute
    rec.execute(self)
  File "/Users/derek/pyramid/myproject/lib/python2.7/site-packages/SQLAlchemy-0.9.8-py2.7-macosx-10.6-intel.egg/sqlalchemy/orm/unitofwork.py", line 479, in execute
    self.dependency_processor.process_deletes(uow, states)
  File "/Users/derek/pyramid/myproject/lib/python2.7/site-packages/SQLAlchemy-0.9.8-py2.7-macosx-10.6-intel.egg/sqlalchemy/orm/dependency.py", line 1023, in process_deletes
    secondary_update, secondary_delete)
  File "/Users/derek/pyramid/myproject/lib/python2.7/site-packages/SQLAlchemy-0.9.8-py2.7-macosx-10.6-intel.egg/sqlalchemy/orm/dependency.py", line 1111, in _run_crud
    result.rowcount)
StaleDataError: DELETE statement on table 'product_categories' expected to delete 1 row(s); Only 0 were matched.

在这种情况下,我是否缺少某种陷阱"?似乎是一个非常标准的实现.为什么要尝试两次执行DELETE语句?

Am I missing some sort of a 'gotcha' in this case? Seems like a pretty standard implementation. Why is it attempting to execute the DELETE statement twice?

推荐答案

经过更多搜索后,我发现以下链接暗示这是一个MySQL错误: https://groups.google.com/forum/#!topic/sqlalchemy/ajYLEuhEB9k

After a bit more searching, I found the following link which suggests it's a MySQL bug: https://groups.google.com/forum/#!topic/sqlalchemy/ajYLEuhEB9k

非常感谢,禁用supports_san_multi_rowcount帮助了!

Thankfully, disabling supports_san_multi_rowcount helped!

engine = engine_from_config(settings, 'sqlalchemy.')
engine.dialect.supports_sane_rowcount = engine.dialect.supports_sane_multi_rowcount = False

对我来说现在足够好了.这是我在处理postgresql的过程中发现的另一个有趣的资源: https://bitbucket.org/zzzeek/sqlalchemy/issue/3015/deletes-exected-twice-when-using

Good enough for me for now. Here's another interesting resources I found along the way dealing with postgresql: https://bitbucket.org/zzzeek/sqlalchemy/issue/3015/deletes-executed-twice-when-using

这篇关于SQLAlchemy尝试两次删除多对多二级关系的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆