def orm_mapping(event=None): # Register table type for grokked ModelBase classes registered = [] for setobject_type in setobject_type_registry.values(): class_name = setobject_type.__name__ table_name = setobject_type.get_table_name() # Create SA table type if setobject_table_registry.get_by_table(table_name) == None: table_type = Table(table_name, metadata, autoload=True) else: table_type = setobject_table_registry.lookup_by_table(table_name) # And register it. setobject_table_registry.register_type(class_name, table_name, table_type) registered.append(class_name) # register all the non-grokked, remaining tables (e.g. user tables) register_remaining_tables(registered) map_tables()
def compute_orm_properties(self, THIS_IS_A_DIRTY_HACK_PROPERTIES_DICT): mappedsotype = setobject_type_registry.lookup(self.target_model.klass) xref_table_class = None sourcetable = setobject_table_registry.lookup_by_class(self.source_model.klass) targettable = setobject_table_registry.lookup_by_class(self.target_model.klass) if self.cardinality.id == 'MANY_TO_ONE' or \ self.cardinality.id == 'ONE(FK)_TO_ONE': # take primary key on our side primaryfk = getattr(sourcetable.c, self.relation.foreignkeycol) primaryidentifier = getattr(targettable.c, mappedsotype.get_primary_key_attr_name()) primaryjoin = (primaryfk == primaryidentifier) secondaryjoin = None elif self.cardinality.id == 'ONE_TO_MANY' or \ self.cardinality.id == 'ONE_TO_ONE(FK)': # take primary key on other side primaryfk = getattr(targettable.c, self.relation.foreignkeycol) primaryidentifier = getattr( sourcetable.c, setobject_type_registry.lookup(self.source_model.klass).get_primary_key_attr_name() ) primaryjoin = (primaryfk == primaryidentifier) secondaryjoin = None elif self.cardinality.id == 'MANY_TO_MANY': # xref! we actually need two clauses here. # Obtain table class: xref_table_class = setobject_table_registry.get_by_table(self.relation.xref_table) if xref_table_class is None: # Class is not mapped (probably not having a primary key or something like that) -> autoload xref_table_class = Table(self.relation.xref_table, metadata, autoload=True, useexisting=True, autoload_with=getUtility(IDbUtility).engine) # Compose two join clauses primaryjoin = (cls.get_primary_key_column() == getattr(xref_table_class.c, self.relation.foreignkeycol)) secondaryjoin = (mappedsotype.get_primary_key_column() == getattr(xref_table_class.c, self.relation.foreignkeycol2)) # add the obtained setobject to our mapped properties if self.cardinality.id == 'MANY_TO_ONE': # This mapping should really not happen here and now. # Instead, the linkage MUST be persisted into # table p2_linkage at save time! THIS_IS_A_DIRTY_HACK_PROPERTIES_DICT[self.attr_name] = orm.relation( mappedsotype, uselist=False, cascade=self.cascade, back_populates=self.back_populates, primaryjoin=primaryjoin, post_update=self.post_update ) relationarguments = { 'uselist' : False, 'cascade' : self.cascade, 'back_populates' : self.back_populates, 'primaryjoin' : primaryjoin, 'post_update' : self.post_update } else: # the other side has the foreign key, store things as a collection order_by = None collection_class = None # This is a special case for the spans as they should not be mapped as ordinary # dictionary, but rather as an orderable dictionary. This is necessary to retain the insert order # as a ordinary dict isn't ordered. Consider this to be implemented in a more generic way if this # use case is occuring for user relations as well. if self.attr_name == 'spans' and self.source_model.klass == 'WidgetType': collection_class=SpanCollectionClass span_table = setobject_table_registry.lookup_by_table('p2_span') order_by=span_table.c.order # This is another special case to ensure the widgets being tab ordered if self.attr_name == 'widgets' and self.source_model.klass == 'FormType': collection_class = WidgetCollectionClass widget_table = setobject_table_registry.lookup_by_table('p2_widget') order_by=widget_table.c.tab_order # Get collection class if collection_class == None: if self.ref_key is None: collection_class = column_mapped_collection(mappedsotype.get_primary_key_column()) else: mapped_column = mappedsotype.get_column(self.ref_key) collection_class = column_mapped_collection(mapped_column) # Compute arguments: relationarguments = { 'back_populates' : self.back_populates, 'collection_class' : collection_class, 'uselist' : True, 'primaryjoin': primaryjoin, 'cascade' : self.cascade, 'post_update' : self.post_update } if order_by is not None: relationarguments['order_by'] = order_by # Set xref table if we got one if xref_table_class is not None: relationarguments['secondary'] = xref_table_class if secondaryjoin is not None: relationarguments['secondaryjoin'] = secondaryjoin return relationarguments