2015-03-03 88 views
3

我有一個product模型是一個多對多的關係,product_categories描述如下:SQLAlchemy的嘗試兩次刪除多對多的關係二級

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')) 
) 

於是,我試圖刪除此對象:

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,但隨後又試圖再次執行它,然後決定它需要拋出異常,因爲它不在那裏。

>>> 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聲明?

+1

我在這裏搜索了一下,發現了幾個例子。幸運的是,有人建議設置以下'engine'選項: 'engine = engine_from_config(settings,'sqlalchemy。')' 'engine.dialect.supports_sane_rowcount = engine.dialect.supports_sane_multi_rowcount = False' 這似乎是已經工作了,謝天謝地! https://groups.google.com/forum/#!topic/sqlalchemy/ajYLEuhEB9k – dhildreth 2015-03-04 03:41:18

回答

5

更有點搜索後,我發現下面的鏈接,表明它是一個MySQL的錯誤: https://groups.google.com/forum/#!topic/sqlalchemy/ajYLEuhEB9k

值得慶幸的是,禁用supports_san_multi_rowcount幫助!

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-executed-twice-when-using