Kam*_*iel 11 python orm sqlalchemy foreign-key-relationship
我有一组看起来像这样的表:
workflows = Table('workflows', Base.metadata,
Column('id', Integer, primary_key=True),
)
actions = Table('actions', Base.metadata,
Column('name', String, primary_key=True),
Column('workflow_id', Integer, ForeignKey(workflows.c.id), primary_key=True),
)
action_dependencies = Table('action_dependencies', Base.metadata,
Column('workflow_id', Integer, ForeignKey(workflows.c.id), primary_key=True),
Column('parent_action', String, ForeignKey(actions.c.name), primary_key=True),
Column('child_action', String, ForeignKey(actions.c.name), primary_key=True),
)
Run Code Online (Sandbox Code Playgroud)
我的ORM类看起来像:
class Workflow(Base):
__table__ = workflows
actions = relationship("Action", order_by="Action.name", backref="workflow")
class Action(Base):
__table__ = actions
children = relationship("Action",
secondary=action_dependencies,
primaryjoin=actions.c.name == action_dependencies.c.parent_action,
secondaryjoin=actions.c.name == action_dependencies.c.child_action,
backref="parents"
)
Run Code Online (Sandbox Code Playgroud)
因此,在我的系统中,每个操作都由工作流ID和名称的组合唯一标识.我希望每个动作都有,parents并且children属性引用其父动作和子动作.每个动作都可以有多个父母和孩子.
当我有一个如下功能时,会出现问题:
def set_parents(session, workflow_id, action_name, parents):
action = session.query(db.Action).filter(db.Action.workflow_id == workflow.id).filter(db.Action.name == action_name).one()
for parent_name in parents:
parent = session.query(db.Action).filter(db.Action.workflow_id == workflow.id).filter(db.Action.name == parent_name).one()
action.parents.append(parent)
session.commit()
Run Code Online (Sandbox Code Playgroud)
我得到一个错误:
IntegrityError: (IntegrityError) action_dependencies.workflow_id may not be NULL u'INSERT INTO action_dependencies (parent_action, child_action) VALUES (?, ?)' (u'directory_creator', u'packing')
Run Code Online (Sandbox Code Playgroud)
如何获得正确设置workflow_id的关系?
van*_*van 12
见下面的工作代码.关键点是我在评论中提到的那些:
ForeignKey小号relationship使用FK 正确配置码:
workflows = Table('workflows', Base.metadata,
Column('id', Integer, primary_key=True),
)
actions = Table('actions', Base.metadata,
Column('workflow_id', Integer, ForeignKey(workflows.c.id), primary_key=True),
Column('name', String, primary_key=True),
)
action_dependencies = Table('action_dependencies', Base.metadata,
Column('workflow_id', Integer, ForeignKey(workflows.c.id), primary_key=True),
Column('parent_action', String, ForeignKey(actions.c.name), primary_key=True),
Column('child_action', String, ForeignKey(actions.c.name), primary_key=True),
ForeignKeyConstraint(['workflow_id', 'parent_action'], ['actions.workflow_id', 'actions.name']),
ForeignKeyConstraint(['workflow_id', 'child_action'], ['actions.workflow_id', 'actions.name']),
)
class Workflow(Base):
__table__ = workflows
actions = relationship("Action", order_by="Action.name", backref="workflow")
class Action(Base):
__table__ = actions
children = relationship("Action",
secondary=action_dependencies,
primaryjoin=and_(actions.c.name == action_dependencies.c.parent_action,
actions.c.workflow_id == action_dependencies.c.workflow_id),
secondaryjoin=and_(actions.c.name == action_dependencies.c.child_action,
actions.c.workflow_id == action_dependencies.c.workflow_id),
backref="parents"
)
# create db schema
Base.metadata.create_all(engine)
# create entities
w_1 = Workflow()
w_2 = Workflow()
a_11 = Action(name="ac-11", workflow=w_1)
a_12 = Action(name="ac-12", workflow=w_1)
a_21 = Action(name="ac-21", workflow=w_2)
a_22 = Action(name="ac-22", workflow=w_2)
session.add(w_1)
session.add(w_2)
a_22.parents.append(a_21)
session.commit()
session.expunge_all()
print '-'*80
# helper functions
def get_workflow(id):
return session.query(Workflow).get(id)
def get_action(name):
return session.query(Action).filter_by(name=name).one()
# test another OK
a_11 = get_action("ac-11")
a_12 = get_action("ac-12")
a_11.children.append(a_12)
session.commit()
session.expunge_all()
print '-'*80
# test KO (THIS SHOULD FAIL VIOLATING FK-constraint)
a_11 = get_action("ac-11")
a_22 = get_action("ac-22")
a_11.children.append(a_22)
session.commit()
session.expunge_all()
print '-'*80
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
14893 次 |
| 最近记录: |