【问题标题】:Access parent object from sqlalchemy association_proxy creator从 sqlalchemy association_proxy 创建者访问父对象
【发布时间】:2016-11-12 01:42:45
【问题描述】:

我需要从 association_proxy 创建者/设置者访问父对象

class File(Base):
    id = Column(INTEGER)
    description = Column(String(1000))
    content = Column(String(10000))

class User(Base):
    name = Column(String(100))
    cv_file_id = Column(INTEGER, ForeignKey(File.id))
    cv_file = relationship(File, uselist=False)
    cv = association_proxy('cv_file', None, 
          creator=lambda v: File(description = 'cv for ' + user.name, content = v),
          ...)

我需要在 creator 方法中引用 user 对象,以便可以使用以下代理

u = User(name = 'John')
u.cv = 'Some cv'
assert u.cv_file.description == 'cv for John'

【问题讨论】:

  • 您找到解决方案了吗?我也有同样的问题。
  • 没有。我只是使用带有 getter/setter 的常用对象,例如:class User(Base): cv = FileDescriptor() class FileDescriptor: def __set__(self, instance, data): # use instance.name

标签: python sqlalchemy associations relationship


【解决方案1】:

我认为不修改类就没有办法解决这个问题。这就是我所做的:

from sqlalchemy.ext import associationproxy
from sqlalchemy import util, exc

def association_proxy(target_collection, attr, **kw):
    return AssociationProxy(target_collection, attr, **kw)


class AssociationProxy(associationproxy.AssociationProxy):
    """AssociationProxy class where creator() is a function
    (parent, value) -> obj, where `parent` is the parent instance,
    `value` is the child instance that is added to the proxy object,
    and `obj` is the object that will reside in the proxy's collection

    For dict classes, the function signature is (parent, key, value) -> obj.
    """
    def _new(self, lazy_collection):
        # Note: this is copied code from SQLAlchemy 1.2.0b1 in order to change
        # association collections used
        creator = self.creator and self.creator or self.target_class
        self.collection_class = util.duck_type_collection(lazy_collection())

        if self.proxy_factory:
            return self.proxy_factory(
                lazy_collection, creator, self.value_attr, self)

        if self.getset_factory:
            getter, setter = self.getset_factory(self.collection_class, self)
        else:
            getter, setter = self._default_getset(self.collection_class)

        # This part is overriden
        if self.collection_class is list:
            return AssociationList(
                lazy_collection, creator, getter, setter, self)
        elif self.collection_class is dict:
            return AssociationDict(
                lazy_collection, creator, getter, setter, self)
        elif self.collection_class is set:
            return AssociationSet(
                lazy_collection, creator, getter, setter, self)
        else:
            raise exc.ArgumentError(
                'could not guess which interface to use for '
                'collection_class "%s" backing "%s"; specify a '
                'proxy_factory and proxy_bulk_set manually' %
                (self.collection_class.__name__, self.target_collection))


class AssociationList(associationproxy._AssociationList):
    def _create(self, value):
        return self.creator(self.lazy_collection.ref(), value)


class AssociationDict(associationproxy._AssociationDict):
    def _create(self, key, value):
        return self.creator(self.lazy_collection.ref(), key, value)


class AssociationSet(associationproxy._AssociationSet):
    def _create(self, value):
        return self.creator(self.lazy_collection.ref(), value)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-09
    • 2017-07-14
    • 2013-04-06
    • 2017-05-08
    • 2010-10-12
    相关资源
    最近更新 更多