1

アソシエーション プロキシで参照のコレクション クラスのキーを変更することは可能ですか?

例:

class Event(ManagerBase):
    """Defines an event."""

    __tablename__ = 'eventing_events'

    id = Column(Integer, primary_key=True)
    device_id = Column(Integer, ForeignKey(EventingDevice.id), nullable=False)
    device = relation(EventingDevice)
    type_id = Column(Integer, ForeignKey(EventType.id), nullable=False)
    type = relation(EventType)
    datetime = Column(DateTime, nullable=False)
    summary = Column(String(500))

    fields = association_proxy("field_values", "value")

class EventFieldValue(ManagerBase):
    """The value of a single field of an event."""

    __tablename__ = 'eventing_event_field_values'

    event_id = Column(Integer, ForeignKey(Event.id), primary_key=True)
    event = relation(Event, backref=backref("field_values",
                                            collection_class=attribute_mapped_collection("field")))
    field_id = Column(Integer, ForeignKey(Field.id), primary_key=True)
    field = relation(Field)
    value = Column(Text)

この場合、 will のfield属性はEventdict をEventFieldValue.fieldキーとして表します。関係に影響を与えることなく、プロキシ自体でのみこのキーを変更することは可能ですか?

4

1 に答える 1

1

クラスが元のリレーションシップに直接アクセスするため、元の SQLAlchemy ではこれが不可能であるように思われるAssociationProxyため、基になるリレーションシップでキーが 1:1 でクエリされます。

DictProxyキーと値のフィールドを変更できるclassを作成しました。

class DictProxy(object):
    def __init__(self, col, keyattr, valattr = None):
        self.obj = None
        self.col = col
        self.keyattr = keyattr
        self.valattr = valattr

    def __get__(self, obj, class_):
        self.obj = obj
        return self

    def __repr__(self):
        outdict = {}
        for k, v in getattr(self.obj, self.col).iteritems():
            if not k is None:
                if self.valattr == None:
                    outdict[getattr(k, self.keyattr)] = v
                elif v is not None:
                    outdict[getattr(k, self.keyattr)] = getattr(v, self.valattr)
                else:
                    outdict[getattr(k, self.keyattr)] = None
        return repr(outdict)

    def __getitem__(self, key):
        keyobj = [obj for obj in getattr(self.obj, self.col) if getattr(obj, self.keyattr) == key]
        if not len(keyobj):
            return None
        if self.valattr == None:
            return getattr(self.obj, self.col)[keyobj[0]]
        else:
            return getattr(getattr(self.obj, self.col)[keyobj[0]], self.valattr)

    def __contains__(self, key):
        return len([obj for obj in getattr(self.obj, self.col) if getattr(obj, self.keyattr) == key]) != 0

def dict_proxy(*arg):
    return DictProxy(*arg)

使用例:

class Event(ManagerBase):
    """Defines an event."""

    __tablename__ = 'eventing_events'

    id = Column(Integer, primary_key=True)
    device_id = Column(Integer, ForeignKey(EventingDevice.id), nullable=False)
    device = relation(EventingDevice)
    type_id = Column(Integer, ForeignKey(EventType.id), nullable=False)
    type = relation(EventType)
    datetime = Column(DateTime, nullable=False)
    summary = Column(String(500))

    fields = dict_proxy("field_values", "name", "value")

fieldsof Eventnow はキーとして を持つ辞書でEventFieldValue.nameあり、リレーション field_values にアクセスします (これはEventFieldValue経由で取得されbackrefます)。

注:__setitem__実際にはこれは読み取り専用のプロキシですが、メソッド を介してプロキシを拡張することは可能かもしれません (注意が必要です) 。

于 2012-06-26T17:34:02.680 に答える