SQLAlchemy对删除的循环依赖

时间:2016-02-02 20:36:34

标签: python sqlalchemy

我在SQLAlchemy 1.0.11

中构建了一些类似下面的模型
class HasID(object):
    @declared_attr
    def id(cls):
        return Column('id', Integer, Sequence('test_id_seq'), primary_key=True)
    ...


class TestParent(HasID, Model)
    __tablename__ = 'tests'
    discriminator = Column(String(50))
    __mapper_args__ = {'polymorphic_on': discriminator}
    ...


class FooTest(TestParent, Model):
    __tablename__ = 'footests'
    __mapper_args__ = {'polymorphic_identity': 'footests'}
    id = Column(Integer, ForeignKey('tests.id'), primary_key=True)
    parent_id = Column(Integer, ForeignKey('footests.id'))
    children = relationship('FooTest',
                            foreign_keys='FooTest.id',
                            lazy='joined',
                            join_depth=2,
                            cascade='save-update, merge, delete, delete-orphan')
    ...


class BarTest(TestParent, Model):
    __tablename__ = 'bartests'
    __mapper_args__ = {'polymorphic_identity': 'bartests'}
    id = Column(Integer, ForeignKey('tests.id'), primary_key=True)
    ...

现在,当我尝试使用以下内容删除BarTest实例时:

mytest = TestParent.query.get(30) # is an instance of BarTest
db_session.delete(mytest)
db_session.commit()

我得到以下追溯:

Connected to pydev debugger (build 143.1559)
Traceback (most recent call last):
  File "/home/xxx/Downloads/pycharm-5.0.3/helpers/pydev/pydevd.py", line 2407, in <module>
    globals = debugger.run(setup['file'], None, None, is_module)
  File "/home/xxx/Downloads/pycharm-5.0.3/helpers/pydev/pydevd.py", line 1798, in run
    launch(file, globals, locals)  # execute the script
  File "/home/xxx/xxx/data_app/scratches/sql_scratcher.py", line 38, in <module>
    db_session.commit()
  File "/home/xxx/xxx/data_app/env/lib/python2.7/site-packages/sqlalchemy/orm/scoping.py", line 150, in do
    return getattr(self.registry(), name)(*args, **kwargs)
  File "/home/xxx/xxx/data_app/env/lib/python2.7/site-packages/sqlalchemy/orm/session.py", line 813, in commit
    self.transaction.commit()
  File "/home/xxx/xxx/data_app/env/lib/python2.7/site-packages/sqlalchemy/orm/session.py", line 392, in commit
    self._prepare_impl()
  File "/home/xxx/xxx/data_app/env/lib/python2.7/site-packages/sqlalchemy/orm/session.py", line 372, in _prepare_impl
    self.session.flush()
  File "/home/xxx/xxx/data_app/env/lib/python2.7/site-packages/sqlalchemy/orm/session.py", line 2027, in flush
    self._flush(objects)
  File "/home/xxx/xxx/data_app/env/lib/python2.7/site-packages/sqlalchemy/orm/session.py", line 2145, in _flush
    transaction.rollback(_capture_exception=True)
  File "/home/xxx/xxx/data_app/env/lib/python2.7/site-packages/sqlalchemy/util/langhelpers.py", line 60, in __exit__
    compat.reraise(exc_type, exc_value, exc_tb)
  File "/home/xxx/xxx/data_app/env/lib/python2.7/site-packages/sqlalchemy/orm/session.py", line 2109, in _flush
    flush_context.execute()
  File "/home/xxx/xxx/data_app/env/lib/python2.7/site-packages/sqlalchemy/orm/unitofwork.py", line 365, in execute
    postsort_actions):
  File "/home/xxx/xxx/data_app/env/lib/python2.7/site-packages/sqlalchemy/util/topological.py", line 36, in sort_as_subsets
    _gen_edges(edges)
sqlalchemy.exc.CircularDependencyError: Circular dependency detected. (DeleteState(<FooTest at 0x7f9b74a2e590>), DeleteState(<FooTest at 0x7f9b74a2e510>))

Process finished with exit code 1

我对如何设置FooTest感到困惑。我正在尝试通过与BarTest进行交互来删除TestParent的实例,尽管在引用FooTest

时出错

1 个答案:

答案 0 :(得分:0)

SQLAlchemy邮件列表之王提供的答案是我需要更改

class FooTest(TestParent, Model):
    __tablename__ = 'footests'
    __mapper_args__ = {'polymorphic_identity': 'footests'}
    id = Column(Integer, ForeignKey('tests.id'), primary_key=True)
    parent_id = Column(Integer, ForeignKey('footests.id'))
    children = relationship('FooTest',
                            foreign_keys='FooTest.id',
                            lazy='joined',
                            join_depth=2,
                            cascade='save-update, merge, delete, delete-orphan')

class FooTest(TestParent):
    __tablename__ = 'footests'
    __mapper_args__ = {'polymorphic_identity': 'footests'}
    id = Column(Integer, ForeignKey('tests.id'), primary_key=True)
    parent_id = Column(Integer, ForeignKey('footests.id'))
    children = relationship('FooTest',
                            foreign_keys='FooTest.parent_id', # CHANGE HERE!!
                            lazy='joined',
                            join_depth=2,
                            cascade='save-update, merge, delete, delete-orphan')

我在FooTest父母和FooTest子女之间的关系中指定了错误的外键。

我还从Model继承中删除了FooTest(根据Boris的评论),虽然这没有造成任何错误