У меня есть класс mixin, который я определяю в начале приложения SQLAlchemy, а затем наследую почти от каждой декларативной модели, которую я использую.
class Owned(object):
@declared_attr
def created_by_id(cls):
return Column(Integer, ForeignKey("accounts.id"),
nullable = True)
@declared_attr
def created_by(cls):
return relationship("Account", foreign_keys = cls.created_by_id)
@declared_attr
def updated_by_id(cls):
return Column(Integer, ForeignKey("accounts.id"),
nullable = True)
@declared_attr
def updated_by(cls):
return relationship("Account", foreign_keys = cls.updated_by_id)
Это хорошо работает для большинства предполагаемых вариантов использования.
class Thing(Owned, Base): # Base is from SQLAlchemy's declarative_base()
pass
account = session.query(Account).first()
thing = Thing(created_by = account, updated_by = account)
session.add(thing)
session.commit()
session.refresh(thing)
assert thing.created_by == account # pass
assert thing.updated_by == account # pass
Тем не менее, я получаю неожиданное поведение, когда определяю Account
как наследовавшееся от Owned
.
class Account(Owned, Base):
pass
account_old = session.query(Account).first()
account_new = Account(created_by = account_old, updated_by = account_old)
session.add(account_new)
session.commit()
session.refresh(account_new)
assert account_new.created_by_id == account_old.id # pass
assert account_new.updated_by_id == account_old.id # pass
# BUT!
assert account_new.created_by == account_old # fail
assert account_new.updated_by == account_old # fail
account_new.created_by # []
account_new.updated_by # []
Я вижу, что в этом случае мне исполнилось created_by_id
и updated_by_id
в самостоятельные внешние ключи.Однако я не понимаю, почему SQLAlchemy не заполняет связанные столбцы relationship
ожидаемыми Account
экземплярами.
Что я делаю не так?