[英]Dependency rule tried to blank out primary key in SQLAlchemy, when foreign key constraint is part of composite primary key
I have the following model definitions 我有以下模型定义
class Foo(Base):
__tablename__ = 'foo'
id = Column(Integer, primary_key=True)
name = Column(String(200))
class FooCycle(Base):
__tablename__ = 'foocycle'
foo_id = Column(
String(50),
ForeignKey('foo.id'),
primary_key=True
)
some_number = Column(
Integer,
primary_key=True,
)
foo = relationship("Foo", backref="cycles")
and the following test case 和以下测试用例
class HierarchicModelTest(unittest.TestCase):
def test_create_data_via_orm_save_twice(self):
# get_session is a convenience wrapper to access a scoped session object
s = get_session()
def create_foo():
foo = Foo(id="12345", name="fancy foo")
foo.cycles = [FooCycle(some_number=1)]
return foo
# initially create foo
foo = create_foo()
s.add(foo)
s.flush()
# recreating foo, using merge to update into database
foo = create_foo()
s.merge(foo)
# raises Exception: Dependency rule tried to blank-out primary key
# column 'foocycle.foo_id' on instance '<FooCycle at 0x32e6b10>'
s.flush()
The test fails with a neat little stack trace and the final assertion error, telling me that the "Dependency rule tried to blank-out primary key column 'foocycle.foo_id". 测试失败,有一个整齐的小堆栈跟踪和最后的断言错误,告诉我“依赖规则试图消除主键列'foocycle.foo_id”。 I'm assuming SQLAlchemy cannot, or doesn't want to calculate the value for foo_id on FooCycle itself.
我假设SQLAlchemy不能,或者不想在FooCycle本身上计算foo_id的值。 I can explicitly set this value myself in
create_foo
: 我可以在
create_foo
自己设置这个值:
def create_foo():
foo = Foo(id="12345", name="fancy foo")
foo.cycles = [FooCycle(some_number=1, foo_id="12345")]
return foo
But, due to conciseness, architectural considerations and admittedly personal pride I don't want to. 但是,由于简洁,建筑方面的考虑和公认的个人自豪感,我不想这样做。 Is there a simple way to get SQLAlchemy to resolve this issue.
是否有一种简单的方法可以让SQLAlchemy解决此问题。 I haven't quite grasped the purpose of the dependency rule.
我还没有完全掌握依赖规则的目的。 Any pointers/information on that issue?
有关该问题的任何指针/信息?
Stack Trace: 堆栈跟踪:
# Test 1 of 7:
# test_core.HierarchicModelTest.test_create_data_via_orm_save_twice
===============
HierarchicModelTest: test_create_data_via_orm_save_twice (tests.test_core.HierarchicModelTest)
Failed test "test_create_data_via_orm_save_twice (tests.test_core.HierarchicModelTest)"! Reason: Dependency rule tried to blank-out primary key column 'foocycle.foo_id' on instance '<FooCycle at 0x39cda10>'
Traceback (most recent call last):
File "/home/xxx/xxx/xxx/backend/tests/test_core.py", line 115, in test_create_data_via_orm_save_twice
s.flush()
File "/home/xxx/xxx/xxx/.env/lib/python2.7/site-packages/sqlalchemy/orm/scoping.py", line 149, in do
return getattr(self.registry(), name)(*args, **kwargs)
File "/home/xxx/xxx/xxx/.env/lib/python2.7/site-packages/sqlalchemy/orm/session.py", line 1879, in flush
self._flush(objects)
File "/home/xxx/xxx/xxx/.env/lib/python2.7/site-packages/sqlalchemy/orm/session.py", line 1997, in _flush
transaction.rollback(_capture_exception=True)
File "/home/xxx/xxx/xxx/.env/lib/python2.7/site-packages/sqlalchemy/util/langhelpers.py", line 57, in __exit__
compat.reraise(exc_type, exc_value, exc_tb)
File "/home/xxx/xxx/xxx/.env/lib/python2.7/site-packages/sqlalchemy/orm/session.py", line 1961, in _flush
flush_context.execute()
File "/home/xxx/xxx/xxx/.env/lib/python2.7/site-packages/sqlalchemy/orm/unitofwork.py", line 370, in execute
rec.execute(self)
File "/home/xxx/xxx/xxx/.env/lib/python2.7/site-packages/sqlalchemy/orm/unitofwork.py", line 479, in execute
self.dependency_processor.process_saves(uow, states)
File "/home/xxx/xxx/xxx/.env/lib/python2.7/site-packages/sqlalchemy/orm/dependency.py", line 552, in process_saves
uowcommit, False)
File "/home/xxx/xxx/xxx/.env/lib/python2.7/site-packages/sqlalchemy/orm/dependency.py", line 569, in _synchronize
sync.clear(dest, self.mapper, self.prop.synchronize_pairs)
File "/home/xxx/xxx/xxx/.env/lib/python2.7/site-packages/sqlalchemy/orm/sync.py", line 53, in clear
(r, orm_util.state_str(dest))
AssertionError: Dependency rule tried to blank-out primary key column 'foocycle.foo_id' on instance '<FooCycle at 0x39cda10>'
Based on the comment by van I was able to work out a solution. 基于van的评论我能够找到解决方案。 The default relationship cascade is
"save-update, merge"
. 默认关系级联是
"save-update, merge"
。 I had to set this to "save-update, merge, delete, delete-orphan"
. 我不得不将其设置为
"save-update, merge, delete, delete-orphan"
。
Adding delete
by itself did not change the behavior, delete-orphan
was necessary. 单独添加
delete
不会改变行为, delete-orphan
是必要的。
Adding only delete-orphan
made a deletion testcase fail, with the "dependency rule" assertion error, mentioned in the question: 仅添加
delete-orphan
使删除测试用例失败,并在问题中提到“依赖关系规则”断言错误:
class HierarchicModelTest(unittest.TestCase):
def test_delete_parent_object(self):
foo = Foo(**foo_data).save()
self.assertEqual(Foo.query.count(), 1)
self.assertEqual(FooCycle.query.count(), 1)
s = get_session()
s.delete(foo)
s.flush()
self.assertEqual(Foo.query.count(), 0)
self.assertEqual(FooCycle.query.count(), 0)
-- -
File "/home/xxx/xxx/xxx/backend/tests/test_core.py", line 128, in test_delete_parent_object
s.flush()
[...]
AssertionError: Dependency rule tried to blank-out primary key column 'foocycle.foo_id' on instance '<FooCycle at 0x37a1710>'
From the SQLAlchemy docs: 从SQLAlchemy文档:
delete-orphan
cascade adds behavior to thedelete
cascade, such that a child object will be marked for deletion when it is de-associated from the parent, not just when the parent is marked for deletion.delete-orphan
cascade将行为添加到delete
级联中,这样当子对象从父级解除关联时,将标记为删除,而不仅仅是在父级被标记为删除时。
So, the correct definition of the FooCycle Model is 因此,FooCycle模型的正确定义是
class FooCycle(Base):
__tablename__ = 'foocycle'
foo_id = Column(
String(50),
ForeignKey('foo.id'),
primary_key=True
)
some_number = Column(
Integer,
primary_key=True,
)
foo = relationship("Foo",
backref=backref("cycles",
cascade="save-update, merge, "
"delete, delete-orphan"))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.