[英]How can I set attributes on a "parent" object if a "child" object is assigned to a "relation" in SQLAlchemy?
当我有两个对象与 SQLAlchemy 中的“关系”相关联时,我意识到仅分配给该关系不足以将值传播到另一个对象。 例如(见下文),如果我有一个“用户”表和一个“联系人”表(两者都是高度人为的,但很好地证明了问题),并且一个“用户”可以有多个“联系人”。 在这种情况下,我将在用户和联系人之间使用外键。 如果我创建的两个实例User
,并Contact
到后来的用户分配到的接触,我希望在FK的属性进行更新(即使没有DB齐平),但事实并非如此。 为什么? 我如何告诉 SA 自动执行此操作?
这将是我期望的工作,但正如您在下面的完整示例中看到的那样,它没有:
user = User(name='a', lname='b')
contact(type='email', value='foo@bar.com')
contact.user = user
assert contact.username == 'a' # <-- Fails because the attribute is still `None`
完整的可运行示例:
"""
This code example shows two tables related to each other by a composite key,
using an SQLAlchemy "relation" to allow easy access to related items.
However, as the last few lines show, simply assigning an object A to the
relation of object B does not update the attributes of object B until at least
a "flush" is called.
"""
from sqlalchemy import Column, ForeignKeyConstraint, Unicode, create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relation, sessionmaker
Base = declarative_base()
class User(Base):
__tablename__ = "user"
name = Column(Unicode, primary_key=True)
lname = Column(Unicode, primary_key=True)
class Contact(Base):
__tablename__ = "contact"
__table_args__ = (
ForeignKeyConstraint(
['username', 'userlname'],
['user.name', 'user.lname']
),
)
username = Column(Unicode, primary_key=True)
userlname = Column(Unicode, primary_key=True)
type = Column(Unicode)
value = Column(Unicode)
user = relation(User)
engine = create_engine('sqlite://')
Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine)
session = Session()
user = User(name="John", lname="Doe")
contact = Contact(type='email', value='john.doe@example.com')
contact.user = user # <-- How can I tell SA to set the FKs on *contact* here?
session.add(contact)
print('Before flush: contact.username user=%r' % contact.username)
session.flush()
print('After flush : contact.username user=%r' % contact.username)
根据这个答案 - https://stackoverflow.com/a/52911047/4981223这是不可能的:
直到您显式或通过 commit() 发出 flush() 后,子对象的 FK 才会更新。 我认为这样做的原因是,如果关系的父对象也是一个带有自增 PK 的新实例,SQLAlchemy 需要从数据库中获取 PK,然后才能更新子对象上的 FK(但我支持待纠正!)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.