我有一个关于SQLAlchemy中实体映射的问题。
我有一个瞬态对象,它已经包含一些持久对象的外键。我希望SQLAlchemy获取引用的对象并将它们分配给它们的关系属性。从SQLAlchemy文档中,我认为我必须在会话上使用合并操作来实现这一点。但在我的配置中,它不起作用。
这是证明我的问题的最低范例:
# -*- coding: utf-8 -*-
from sqlalchemy import create_engine
from sqlalchemy.orm import mapper
from sqlalchemy import Table, Column, Integer, String, MetaData, ForeignKey
from sqlalchemy.orm import relationship, sessionmaker
class User(object):
def __init__(self, id, name, fullname, password, best_friend_id=None):
self.id = id
self.name = name
self.fullname = fullname
self.password = password
self.best_friend_id = best_friend_id
def __repr__(self):
return "<User('%s','%s', '%s')>" % (self.name, self.fullname, self.password)
class Dog(object):
def __init__(self, id, name):
self.id = id
self.name = name
def __repr__(self):
return "<User('%s','%s', '%s')>" % (self.name, self.fullname, self.password)
engine = create_engine('sqlite:///:memory:', echo=True)
Session = sessionmaker(bind=engine)
session = Session()
metadata = MetaData()
dogs_table = Table('dogs', metadata,
Column('id', Integer, primary_key=True),
Column('name', String),
)
users_table = Table('users', metadata,
Column('id', Integer, primary_key=True),
Column('name', String),
Column('fullname', String),
Column('password', String),
Column('best_friend_id', Integer, ForeignKey('dogs.id'))
)
metadata.create_all(engine)
mapper(User, users_table, properties={'best_friend': relationship(Dog, uselist=False)})
mapper(Dog, dogs_table)
dog = Dog(id=1, name='Hasso')
lordling = User(id=2, name='John', fullname='Miller', password='very_secret', best_friend_id=1)
session.add(dog)
session.commit()
merged_lordling = session.merge(lordling)
print str(merged_lordling.best_friend.name)
我希望merged_lordling.best_friend
包含狗'Hasso'。但它仍然是None
。
答案 0 :(得分:1)
我最近有点同样的问题。建立关系后,您应该直接将Dog
实例分配给User.best_friend
,而不是明确地使用外键。我不知道为什么会发生这种情况,但在调查类似的问题时,我意识到如果你这样做,SQLAlchemy不会填充关系属性,直到你刷新所有相关的实例。
所以,而不是:
dog = Dog(id=1, name='Hasso')
lordling = User(id=2, name='John', fullname='Miller', password='very_secret',
best_friend_id=1)
session.add(dog)
简单地说:
dog = Dog(id=1, name='Hasso')
lordling = User(id=2, name='John', fullname='Miller', password='very_secret',
best_friend=dog)
session.add(lordling)
甚至:
lordling = User(id=2, name='John', fullname='Miller', password='very_secret',
best_friend=Dog(id=1, name='Hasso'))
session.add(lordling)
作为一般规则,请避免在建立关系时直接使用外键列。拥抱ORM,只有在没有其他选择时才直接从外键分配或查询。我学到了很难的方法。