我有两种类型的对象:
ValueObjects
继承自BaseValueObject
和Addendum
- 带注释的对象。 Addendum
具有特定注释(属性:name
,description
,flag
)和一般注释((badgetype, badgevalue)
),其中badgevalue
是存储在Badge
- 对象和badgetype in an
AddendumBadgeMap`对象中。
现在,我想访问
name
,description
和flag
作为ValueOjects
和Badges
直接来自ValueOjects
作为字典。以下是一个示例实现:
import sqlalchemy as sa
import sqlalchemy.orm as orm
from sqlalchemy.orm import scoped_session, sessionmaker
from sqlalchemy.ext.declarative import declarative_base
DBSession = scoped_session(sessionmaker())
Base = declarative_base ()
###### ValueObjects: ##########
class BaseValueObject(Base):
__tablename__ = 'value_objects'
id = sa.Column(sa.Integer, primary_key=True)
vo_type = sa.Column (sa.String, nullable=False)
__mapper_args__ = {'polymorphic_on': vo_type}
class ObjectOne(BaseValueObject):
__tablename__ = 'objects_one'
__mapper_args__ = {'polymorphic_identity': 'ObjectOne'}
id = sa.Column(sa.ForeignKey('value_objects.id'), primary_key=True)
any_attribute = sa.Column(sa.String)
class ObjectTwo(BaseValueObject):
__tablename__ = 'objects_two'
__mapper_args__ = {'polymorphic_identity': 'ObjectTwo'}
id = sa.Column(sa.ForeignKey('value_objects.id'), primary_key=True)
any_attribute = sa.Column(sa.String)
###############################
##### Addendum and Bagde ##########
class Addendum(Base):
__tablename__ = 'addenda'
__table_args__ = (
sa.UniqueConstraint('name', 'id'),
{}
)
id = sa.Column (sa.Integer, primary_key=True)
name = sa.Column (sa.String, nullable=False, default='')
description = sa.Column (sa.String, nullable=False, default='')
flag = sa.Column ( sa.Boolean, nullable=False, default=False)
value_object_id = sa.Column ( sa.ForeignKey ('value_objects.id'),
unique=True)
class Badge(Base):
__tablename__ = 'badges'
id = sa.Column (sa.Integer, primary_key=True)
value = sa.Column (sa.String)
class AddendumBadgeMap(Base):
__tablename__ = 'addendum_badge_maps'
__table_args__ = (
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('badge_id', 'badge_type'),
{}
)
id = sa.Column('id', sa.Integer)
addendum_id = sa.Column(sa.ForeignKey('addenda.id'), nullable=False)
badge_id = sa.Column(sa.ForeignKey('badges.id'), nullable=False)
badge_type = sa.Column (sa.String)
###################################
if __name__ == '__main__':
engine = sa.create_engine('sqlite:///:memory:', echo=True)
DBSession.configure(bind=engine)
Base.metadata.create_all(engine)
session = DBSession()
o1 = ObjectOne(any_attribute="test1")
session.add(o1)
session.commit()
我必须补充一点,我可以执行以下操作:
o1.name = "my_name"
# => `Addendum` will be attached with `name="my_name"`
o1.description = "my_description"
# => `descrpiption` of the attached `Addendum` get's changed
o1.flag
# => same behavior (in general: there should be max. one `Addendum` per `ValueObject`)
o1.bagdes = {"file_origin": "/home/.."}
# => attach to the `Addendum` a `Badge` with `value="/home/.."` and
# `AddendumBagdeMap.badge_type="file_origin"` (if `Addendum` does
# not exist for this `ValueObject`: create it first)
答案 0 :(得分:0)
一个解决方案需要实现两部分:
Addendum
Addendum.badges
中的新属性
醇>
第1部分:复合关联代理的实施
将以下属性添加到BaseValueObject
:
Addendum
以及以下badges = association_proxy (
'addendum_badge_maps',
'badge_value',
creator=lambda bt, bv:
AddendumBadgeMap(badge_type=bt, badge_value=bv)
)
:
AddendumBadgeMap
现在,向addendum = orm.relationship(Addendum, backref=orm.backref(
'addendum_badge_maps',
collection_class = attribute_mapped_collection("badge_type"),
cascade="all, delete-orphan")
)
badge = orm.relationship('Badge',
single_parent=True,
)
badge_value = association_proxy ('badge', 'value')
添加__init__
- 方法:
Badge
并在顶部添加以下导入:
def __init__(self, value):
self.value = value
第2部分:从from sqlalchemy.ext.associationproxy import association_proxy
from sqlalchemy.orm.collections import attribute_mapped_collection
访问badge
- 代理
通过向BaseValueObjects
添加属性,将Addendum
- 对象链接到BaseValueObjects
:
Addendum
要访问base_value_object = orm.relationship(
"BaseValueObject",
backref=orm.backref('addendum', uselist=False)
)
,请将以下内容添加到badegs
:
BaseValueObjects
完整代码
def add_badge(self, badge_dict={}, **kwargs):
if self.addendum is None:
self.addendum = Addendum()
badge_dict.update(kwargs)
self.addendum.badges = badge_dict
_name = association_proxy('addendum', 'name',
creator=lambda name: Addendum(
name=name, description='', flag=False))
_description = association_proxy('addendum', 'description',
creator=lambda description: Addendum(
name='', description=description, flag=False))
_flag = association_proxy('addendum', 'flag',
creator=lambda flag: Addendum(
name='', description='', flag=flag))
@property
def badges(self):
try:
return self.addendum.badges
except AttributeError:
"In case that there is no ``Addendum`` specified, yet."
return None
@badges.setter
def badges(self, value):
self.add_badge(value)
@property
def name(self):
try:
return self._name
except AttributeError:
"In case that there is no ``Addendum`` specified, yet."
return ""
@name.setter
def name(self, value):
self._name = value
@property
def description(self):
try:
return self._description
except AttributeError:
"In case that there is no ``Addendum`` specified, yet."
return ""
@description.setter
def description(self, value):
self._description = value
@property
def flag(self):
try:
return self._flag
except AttributeError:
"In case that there is no ``Addendum`` specified, yet."
return ""
@flag.setter
def flag(self, value):
self._flag = value