def interface(cls, name, uselist=True): mapper = class_mapper(cls) table = mapper.local_table mapper.add_property(attr_name, relationship(GenericAssoc, backref='_backref_%s' % table.name) ) if uselist: # list based property decorator def get(self): if getattr(self, attr_name) is None: setattr(self, attr_name, GenericAssoc(table.name)) return getattr(self, attr_name).targets setattr(cls, name, property(get)) else: # scalar based property decorator def get(self): return getattr(self, attr_name).targets[0] def set(self, value): if getattr(self, attr_name) is None: setattr(self, attr_name, GenericAssoc(table.name)) getattr(self, attr_name).targets = [value] setattr(cls, name, property(get, set))
def addressable(cls, name, uselist=True): """addressable 'interface'. if you really wanted to make a "generic" version of this function, it's straightforward. """ # create_address function, imitaes the rails example. # we could probably use property tricks as well to set # the Address object's "addressabletype" attribute. def create_address(self): a = Address(table.name) if uselist: getattr(self, name).append(a) else: setattr(self, name, a) return a mapper = class_mapper(cls) table = mapper.local_table cls.create_address = create_address # no constraints. therefore define constraints in an ad-hoc fashion. primaryjoin = and_( list(table.primary_key)[0] == addresses.c.addressable_id, addresses.c.addressable_type == table.name ) foreign_keys = [addresses.c.addressable_id] mapper.add_property(name, relationship( Address, primaryjoin=primaryjoin, uselist=uselist, foreign_keys=foreign_keys, backref=backref('_backref_%s' % table.name, primaryjoin=list(table.primary_key)[0] == addresses.c.addressable_id, foreign_keys=foreign_keys) ) )
def config_keyable(cls,name="settings"): """Object - List Mixin/Mutator""" mapper = class_mapper(cls) table = mapper.local_table cls_name = str(cls) cls_name = cls_name[cls_name.rfind('.')+1:cls_name.rfind('\'')].lower() mapper.add_property(name, dynamic_loader(ConfigAttribute, primaryjoin=and_(table.c.id==configattribute_table.c.object_id,configattribute_table.c.object_type==cls_name), foreign_keys=[configattribute_table.c.object_id], backref='%s' % table.name)) # initialize some stuff def on_new(self): self.object_type = cls_name setattr(cls, "on_new", on_new)
def userlistable(cls,name="users"): """User - List Mixin/Mutator""" mapper = class_mapper(cls) table = mapper.local_table cls_name = str(cls) cls_name = cls_name[cls_name.rfind('.')+1:cls_name.rfind('\'')].lower() mapper.add_property(name, dynamic_loader(UserAttribute, primaryjoin=and_(table.c.id==userattribute_table.c.object_id,userattribute_table.c.object_type==cls_name), foreign_keys=[userattribute_table.c.object_id], backref='%s' % table.name)) #log.debug("userlistable table.name = %s" % table.name) # initialize some stuff def on_new(self): self.object_type = cls_name setattr(cls, "on_new", on_new)
def versionable(cls,name): """Versionable Mixin/Mutator""" mapper = class_mapper(cls) table = mapper.local_table cls_name = str(cls) cls_name = cls_name[cls_name.rfind('.')+1:cls_name.rfind('\'')].lower() mapper.add_property('versions', dynamic_loader(Version, primaryjoin=and_(table.c.id==version.c.object_id,version.c.object_type==cls_name), foreign_keys=[version.c.object_id], backref='%ss' % table.name)) # most recent version def version_latest(self): if self.versions is None: return None return self.versions.order_by(version.c.version.desc()).first() setattr(cls, "version_latest", property(version_latest))
def add_property(self, name, property, check_duplicate=True): if check_duplicate and name in self.properties: raise Exception("property '%s' already exist in '%s' ! " % (name, self.entity.__name__)) self.properties[name] = property #FIXME: something like this is needed to propagate the relationships from # parent entities to their children in a concrete inheritance scenario. But # this doesn't work because of the backref matching code. # if self.children and self.inheritance == 'concrete': # for child in self.children: # child._descriptor.add_property(name, property) mapper = self.entity.mapper if mapper: mapper.add_property(name, property) if DEBUG: print "mapper.add_property('%s', %s)" % (name, repr(property))
def add_property(self, name, property, check_duplicate=True): if check_duplicate and name in self.properties: raise Exception("property '%s' already exist in '%s' ! " % (name, self.entity.__name__)) self.properties[name] = property #FIXME: something like this is needed to propagate the relationships from # parent entities to their children in a concrete inheritance scenario. But # this doesn't work because of the backref matching code. In most case # (test_concrete.py) it doesn't even happen at all. # if self.children and self.inheritance == 'concrete': # for child in self.children: # child._descriptor.add_property(name, property) mapper = self.entity.mapper if mapper: mapper.add_property(name, property) if DEBUG: print "mapper.add_property('%s', %s)" % (name, repr(property))