这是一些代码:
# latest version at https://gist.github.com/nickretallack/11059102
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, ForeignKey, Integer, String
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker, relationship
Base = declarative_base()
class Parent(Base):
__tablename__ = 'parent'
id = Column(Integer, primary_key=True)
name = Column(String, nullable=False, unique=True)
def __str__(self):
return self.name
class Child(Base):
__tablename__ = 'child'
id = Column(Integer, primary_key=True)
parent_id = Column(ForeignKey(Parent.id), nullable=False)
name = Column(String, nullable=False)
parent = relationship(Parent)
engine = create_engine('sqlite:///:memory:', echo=True)
Session = sessionmaker(bind=engine)
def run():
# Basic Setup
Base.metadata.create_all(engine)
session = Session()
fred = Parent(name="Fred", id=1)
george = Parent(name="George", id=2)
session.add(fred, george)
session.commit()
# The test
bob = Child(name="Bob", parent_id=1)
print bob.parent, ": Out of session. Should be Fred but is None.\n"
session.add(bob)
print bob.parent, ": In session. Should be Fred but is None.\n"
session.commit()
print bob.parent, ": Committed. Is Fred.\n"
bob.parent_id = 2
print bob.parent, ": Dirty. Should be George but is Fred.\n"
session.add(bob)
print bob.parent, ": Added to session. Should be George but is Fred.\n"
session.expire(bob,['parent'])
print bob.parent, ": Expired. Should be George but is None? Wtf?\n"
session.commit()
print bob.parent, ": Committed again. Is None. Ugh.\n"
if __name__ == '__main__':
run()
此示例表明,仅设置关系所依赖的外键字段永远不足以使关系查询正确的内容。无论我做什么,这种情况都会发生。
是否可以让 sqlalchemy 根据当前外键值填充关系,而无需先保留记录?我可以做些什么来让它运行查询吗?
在处理 Web 表单时,这个问题经常出现。表单帖子只包含事物的 ID,因此处理帖子的最简单方法是在记录中设置 ID 字段并尝试提交它,如果引用的项目不存在,或者存在某些项目,则让事务失败只有数据库才能真正了解的其他问题,而不会冒竞争条件的风险,例如违反唯一约束。一旦事务失败,您可能希望向用户重新显示表单。不幸的是,这些关系都不再正确了。
这可能是问题,也可能不是问题,但就我而言,这非常令人沮丧。为了纠正这些关系,我需要复制这些关系中的逻辑,因为我找不到一种方法来告诉他们只进行查询。