2016-07-09 115 views
2

我需要从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), 
      ...) 

我需要参照用户对象在创建者方法,使人们可以使用代理如下

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

您是否找到了解决方案?我有同样的问题。 – Saulpila

+1

号我只是用通常的物体的getter/setter 类似: '类用户(碱): CV =的FileDescriptor() 类的FileDescriptor: DEF __set __(自,例如,数据): #使用instance.name' – kakabomba

回答

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)