def update(self): self.mode = self.request.form.get('mode') setobject_id = self.request.form.get('setobject_id') self.graph_xml = self.request.form.get('graph') if self.graph_xml != None: del(self.request.form['graph']) self.source_id = self.request.form.get('source_id') if self.source_id != None: # Delete request's source_id, as subforms should not see it. del(self.request.form['source_id']) self.linked = self.request.form.get('linked') if self.linked != None: del(self.request.form['linked']) if self.linked != None and self.linked != 'true' and self.linked != 'false': raise Exception("Invalid value for parameter linked") if self.source_id != None and self.linked == None: raise Exception("source_id parameter must be accompanied by linked parameter") if self.linked != None and self.source_id == None: raise Exception("linked parameter must be accompanied by linked source_id parameter.") self.relation_source_id = self.request.form.get('relation_source_id') db_utility = getUtility(IDbUtility) session = db_utility.Session() if self.mode == 'OPERATIONAL': classname = self.context.op_setobject_type.__name__ elif self.mode == 'DESIGNER' or self.mode == 'ARCHETYPE': classname = self.context.__class__.__name__ else: raise Exception("Mode must have one of the values ARCHETYPE, DESIGNER, OPERATIONAL") self.klass = setobject_type_registry.lookup(classname) if not setobject_id: setobject = self.klass() session.add(setobject) setobject_id = setobject.id session.flush() if self.graph_xml != None and self.graph_xml != '': graph = SetobjectGraph(self.request, self.graph_xml) graph.link(self.source_id, classname, setobject_id, self.linked) if setobject_id != None: self.setobject = session.query(self.klass).filter(self.klass.get_primary_key_attr() == setobject_id).one() relation_id = self.request.get('relation_id') if relation_id != None: if self.relation_source_id == None: raise Exception("relation_id parameter must be accompanied by relation_source_id.") self.relation = session.query(EmbeddedForm).filter_by(span_identifier=relation_id).one() source_type = setobject_type_registry.lookup(self.relation.linkage.source_model.klass) self.relation_source = session.query(source_type).filter(source_type.get_primary_key_attr() == self.relation_source_id).one() if self.graph_xml != None and self.graph_xml != '': # Each query after graph.link() call might generate new dynamic linkage id's. Correct them if necessary. graph.update_collections() self.context = self.setobject
def init_xref_relation(self): # Get some vars beforehand: type1 = setobject_type_registry.lookup(self.source_module, self.source_classname) type2 = setobject_type_registry.lookup(self.target_module, self.target_classname) table1class = type1.get_table_class() table2class = type2.get_table_class() table1primarykey = type1.get_primary_key_attr_name() table2primarykey = type2.get_primary_key_attr_name() table1name = type1.get_table_name() table2name = type2.get_table_name() if self.relation.foreignkeycol.lower() == self.relation.foreignkeycol2.lower(): raise UserException("Please choose different column names for both of the two foreign key columns") # Create/obtain xref table fkcol1 = Column( self.relation.foreignkeycol, getattr(table1class.c, table1primarykey).type, ForeignKey(table1name + "." + table1primarykey) ) fkcol2 = Column( self.relation.foreignkeycol2, getattr(table2class.c, table2primarykey).type, ForeignKey(table2name + "." + table2primarykey) ) mytable = Table(self.relation.xref_table, metadata, useexisting=True) if not mytable.exists(): # Create table with new columns mytable = Table(self.relation.xref_table, metadata, fkcol1, fkcol2, Column('id', Integer(8), primary_key=True, autoincrement=True, default=0, nullable=False), useexisting=True, mysql_engine='InnoDB') # Register table type setobject_table_registry.register_type('p2.datashackle.core.models.model', self.relation.xref_table, self.relation.xref_table, mytable) # Create table mytable.create() # Create setobject type create_basemodel_type(self.relation.xref_table, self.relation.xref_table) else: # Alter table to have the new columns if they aren't there yet mytable = Table(self.relation.xref_table, metadata, autoload=True, useexisting=True) if hasattr(mytable.c, self.relation.foreignkeycol) != True: # add fkcol1 fkcol1.create(mytable) if hasattr(mytable.c, self.relation.foreignkeycol2) != True: # add fkcol2 fkcol2.create(mytable) # Remap xref table setobject setobject_type_registry.lookup_by_table(self.relation.xref_table).sa_map()
def __init__(self, span_name=None): self.required = True ft = setobject_type_registry.lookup('p2_fieldtype') sess = getUtility(IDbUtility).Session() self.field_type = sess.query(ft).filter_by(field_type='textline').one() self.style = "left:" + str(self.label_width) + "px; width:" + str(self.label_width) + "px;" super(Alphanumeric, self).__init__(span_name)
def _create_relation(self): if self.cardinality.id == 'ONE_TO_MANY' or \ self.cardinality.id == 'ONE_TO_ONE(FK)': # Create Foreign key and re-map setobject if necessary self.check_create_fk( self.target_table, self.source_table, ignoreexisting=True ) return elif self.cardinality.id == 'MANY_TO_ONE' or \ self.cardinality.id == 'ONE(FK)_TO_ONE': # Create Foreign key and re-map setobject if necessary self.check_create_fk( self.source_table, self.target_table, ignoreexisting=True ) return elif self.cardinality.id == 'MANY_TO_MANY': if self.source_classname.lower() == self.target_classname.lower() and self.source_module.lower() == self.target_module.lower(): raise UserException("You cannot add a relation from a plan to itself (or another plan on the same table)") self.init_xref_relation() # update session and remap source table getUtility(IDbUtility).Session().flush() sourceobj = setobject_type_registry.lookup(self.source_module, self.source_classname) sourceobj.sa_map()
def map_tables(exclude_sys_tables=False): # Map bootstrap orm Linkage object (and dependent objects # Relation and Cardinality) by hand if not exclude_sys_tables: for klass in BOOTSTRAP_CLASSES: class_ = setobject_type_registry.lookup(klass) class_.sa_map() # First, create all properties for the orm.relation method. This is a separate step, # as we use the sqlalchemy orm query object that requires all mapping acitvies are in a consistent state. # This we can only guarantee before and after the mapping process. Therefore we do it before. for setobject_type in setobject_type_registry.values(): if needs_mapping(setobject_type, exclude_sys_tables): try: setobject_type.compute_mapper_properties() except NoPrimaryKeyException: # Table has no primary key, don't map it table_identifier = setobject_type.get_table_name() setobject_type_registry.delete_by_table(table_identifier) setobject_table_registry.delete_by_table(table_identifier) # In a second step we do the actual mapping with the already computed properties # Map table type to ORM setobject type for setobject_type in setobject_type_registry.values(): if needs_mapping(setobject_type, exclude_sys_tables): setobject_type.map_computed_properties()
def post_order_traverse(self, mode): if mode == 'save': klass = setobject_type_registry.lookup(self.op_setobject_type.__name__) table_name = klass.get_table_name() map_field_attr( table_name, self.field_identifier, String(255))
def sa_map(cls): #cls.sa_map_dispose() #cardinality_type.sa_map_dispose() #orm.mapper(cardinality_type, cardinality_table) Relation = setobject_type_registry.lookup('Relation') StrippedModel = setobject_type_registry.lookup('StrippedModel') orm.mapper(cls, cls.get_table_class(), properties={'relation': orm.relation( Relation, uselist=False, primaryjoin = (Relation.get_table_class().c.id == cls.get_table_class().c.fk_p2_relation)), 'source_model': orm.relation(StrippedModel, uselist=False, primaryjoin= (StrippedModel.get_table_class().c.plan_identifier == cls.get_table_class().c.fk_source_model), enable_typechecks=False), 'target_model': orm.relation(StrippedModel, uselist=False, primaryjoin= (StrippedModel.get_table_class().c.plan_identifier == cls.get_table_class().c.fk_target_model), enable_typechecks=False) } )
def pre_order_traverse(self): if self.form == None: raise Exception("Can't finish initialization without the form attribute set.") # set op_setobject_type from parent form's attributes self.op_setobject_type = setobject_type_registry.lookup(self.form.klass) for span in self.spans.itervalues(): span.widget = self span.op_setobject_type = self.op_setobject_type
def sa_map(cls): cardinality_type = setobject_type_registry.lookup( 'Cardinality' ) orm.mapper(cls, cls.get_table_class(), properties={'cardinality': orm.relation( cardinality_type, uselist=False, )}, )
def _each_collection(self, node, setobject): if node.tag == 'obj': typename = node.get('type') klass = setobject_type_registry.lookup(typename) objid = node.get('objid') setobject = self.session.query(klass).get(objid) assert(setobject != None) for child in node: self._each_collection(child, setobject) # post order processing if node.tag == 'obj': self.process_collection_ids(node, setobject)
def do_linkage(self, node, setobject, parent_setobject): linked = node.get('linked') if linked != None: if node.tag != 'obj': raise UnspecificException("Linked node must be of type obj.") collection_node = node.getparent() if collection_node.tag != 'coll': # Parent is not of type coll. # Ignore it. return attr_name = collection_node.get('attr_name') span_identifier = collection_node.get('span_identifier') linkage = parent_setobject.collections[attr_name]['linkage'] refkey = linkage.ref_key if linkage.use_list: coll = getattr(parent_setobject, attr_name) # Refkey: If there's a refkey the value of the key is searched within the object's properties. # If there's no refkey specified, we use the objid itself. key = None if refkey == None: key = node.get('objid') else: key = getattr(setobject, refkey) # Do actual linkage if linked == 'true': coll[key] = setobject elif linked == 'false': if key in coll: del coll[key] else: raise UnspecificException("Invalid link state.") else: if linked == 'true': span_identifier = node.get('span_identifier') if span_identifier is not None: session = getUtility(IDbUtility).Session() span_type = setobject_type_registry.lookup('SpanType') span = session.query(span_type).get(span_identifier) setobject = span.onbefore_set_payload_attribute( setobject=parent_setobject, attribute=attr_name, value=setobject, mode=self.mode ) parent_setobject.set_attribute( attribute=attr_name, value=setobject, mode=self.mode ) # This flush is necessary. Otherwise it seems that if another reference to THIS object is # subsquently deleted via del coll[key], this linkage will not be persisted. self.session.flush()
def compute_mapper_properties(cls): cls.get_primary_key_column() # make sure we have one! (will throw exception if that is not the case) properties = {} cls.fetch_linkages() for linkage in cls.linkages.itervalues(): mappedsotype = setobject_type_registry.lookup( linkage.target_model.klass) if linkage.cardinality.id != 'NONE': # TODO: Don't pass properties. This is a nasty hack! mapper_properties = linkage.compute_orm_properties(properties) properties[linkage.attr_name] = orm.relation(mappedsotype, **mapper_properties) cls.mapper_properties = properties
def __setattr__(self, name, value): super(Dropdown, self).__setattr__(name, value) if name == 'linkage': if self.plan_identifier != None and value != None: # Get the table identifier from our plan identifier and set it as the linkage's target class table = setobject_table_registry.lookup_by_table('p2_model') plan = getUtility(IDbUtility).engine.execute(table.select(table.c.plan_identifier == self.plan_identifier)).first() plan_type = plan['so_type'] table_identifier = setobject_type_registry.lookup(plan_type).get_table_name() oldtargetclass = None try: oldtargetclass = self.linkage.target_classname except AttributeError: pass if oldtargetclass == None or oldtargetclass == "": self.linkage.target_classname = table_identifier
def query_not_joined(self): session = getUtility(IDbUtility).Session() plan_id = self.relation.plan_identifier from p2.datashackle.management.model.model import Model plan = session.query(Model).get(plan_id) target_type = setobject_type_registry.lookup(plan.klass) query = session.query(target_type) query = query.add_column(literal_column("'false'").label("linked")) if ( hasattr(self.relation, "filter_clause") and self.relation.filter_clause != None and len(self.relation.filter_clause) > 0 ): query = query.filter(self.relation.filter_clause) return query
def post_order_traverse(self, mode): if mode == 'save': from p2.datashackle.management.model.model import Model plan_id = self.plan_identifier session = Session() plan = session.query(Model).filter_by(plan_identifier=plan_id).one() source_type = self.op_setobject_type target_type = setobject_type_registry.lookup(plan.klass) # set relation value self.relation.source_table = source_type.get_table_name() self.relation.target_table = target_type.get_table_name() self.relation.create_relation('LIST') # Set computed linkage values self.linkage.source_model = plan m = session.query(Model).filter_by(klass=plan.klass).one() self.linkage.target_model = m
def post_order_processing(self, node, setobject, parent_setobject): if node.tag == 'root': return if node.tag == 'obj': self.do_linkage(node, setobject, parent_setobject) action = node.get('action') if node.tag == 'coll' and node.get('span_identifier') != None: span_identifier = node.get('span_identifier') session = getUtility(IDbUtility).Session() span_type = setobject_type_registry.lookup('SpanType') span = session.query(span_type).get(span_identifier) span.onbefore_post_order_traverse(setobject, self.mode) elif node.tag == 'obj' and node.get('action') != 'delete': setobject.post_order_traverse(self.mode) if node.tag == 'obj': if self.mode == 'save' and action == 'delete': self.session.delete(setobject) else: self.process_collection_ids(node, setobject)
def post_order_traverse(self, mode): if mode == 'save': from p2.datashackle.management.model.model import Model plan_id = self.plan_identifier session = Session() plan = session.query(Model).filter_by(plan_identifier=plan_id).one() source_type = self.op_setobject_type target_type = setobject_type_registry.lookup(plan.klass) # Set computed values on inner objects m = session.query(Model).filter_by(klass=source_type.__name__).one() self.linkage.source_model = m m = session.query(Model).filter_by(klass=plan.klass).one() self.linkage.target_model = m self.linkage.relation.source_table = source_type.get_table_name() self.linkage.relation.target_table = target_type.get_table_name() if self.linkage.relation.cardinality.id != 'NONE': self.linkage.relation.create_relation()
def callback(coll_node): if coll_node.get('linkage_id') == collection_id: # Check if setobject is already in xml found = False for child in coll_node: if child.get('objid') == setobject_id: found = True break if not found: if __debug__: klass = setobject_type_registry.lookup(classname) assert(self.session.query(klass).get(setobject_id) != None) obj = etree.Element("obj") # The setobject MUST already be present in sqlalchemy session. # Through action 'save' it is later queried again. obj.set('action', 'save') obj.set('objid', setobject_id) obj.set('linked', linked) obj.set('type', classname) coll_node.append(obj)
def dfs_main(self, node, setobject, callback, parent_setobject=None): descend = True preceding_setobject = setobject if node.tag == 'prop': attribute = node.get('name') value = node.text span_identifier = node.get('span_identifier') # Not all props have span_identifiers (e.g. css), because # these are not visualized as spans if span_identifier is not None: session = getUtility(IDbUtility).Session() span_type = setobject_type_registry.lookup('SpanType') span = session.query(span_type).get(span_identifier) assert(span != None) value = span.onbefore_set_payload_attribute(setobject, attribute, value, self.mode) setobject.set_attribute(attribute, value, self.mode) elif node.tag == 'obj': # Method sets up a processing scope which results # in new assignment of setobject. setobject, descend = self.process_object(node, parent_setobject) elif node.tag == 'coll': if self.mode == 'link': callback(node) attr_name = node.get('attr_name') linkage = setobject.collections[attr_name]['linkage'] if setobject.action != 'new' and linkage.relation.cardinality.id == 'MANY_TO_ONE': # Set the attribute to None. If it's still linked, it will be done # so in do_linkage, but if not anymore, the attribute is deleted here. setattr(setobject, attr_name, None) elif node.tag == 'root': pass else: # Unknown/invalid node. raise SetobjectGraphException("Unknown node '" + node.tag + "'") if descend: # Traverse deeper into graph for child in node: self.dfs_main(child, setobject, callback, preceding_setobject) self.post_order_processing(node, setobject, preceding_setobject)
def table_identifier(self): """The table on which this plan is operating.""" klass = setobject_type_registry.lookup(self.klass) return klass.get_table_name()
def query_joined(self, query_mode): if query_mode == None: if ( self.relation.linkage.cardinality.id == "ONE(FK)_TO_ONE" or self.relation.linkage.cardinality.id == "ONE_TO_ONE(FK)" ): query_mode = QueryMode.WITH_UNLINKED else: query_mode = QueryMode.SHARED source_type = setobject_type_registry.lookup(self.relation.linkage.source_model.klass) target_type = setobject_type_registry.lookup(self.relation.linkage.target_model.klass) session = getUtility(IDbUtility).Session() if target_type == source_type: target_type = aliased(source_type) # Check if it is an xref relation xref_object = None if self.relation.linkage.cardinality.id == "MANY_TO_MANY": xref_object = setobject_type_registry.lookup_by_table(self.relation.linkage.xref_table) # Compose query for various modes: if query_mode == QueryMode.SHARED: query = session.query(target_type) # For n:m, we need to outerjoin the xref table first: if not xref_object == None: query = query.outerjoin( ( xref_object, target_type.get_primary_key_attr() == getattr(xref_object, self.relation.linkage.relation.foreignkeycol2), ) ) # Simply join with our source table from the target table. The join condition ensures we either get linked elements, or the source table's primary key field will be null/None. if xref_object == None: if ( self.relation.linkage.cardinality.id == "ONE_TO_MANY" or self.relation.linkage.cardinality.id == "ONE_TO_ONE(FK)" ): joincondition = getattr(source_type, source_type.get_primary_key_attr_name()) == getattr( target_type, self.relation.linkage.relation.foreignkeycol ) else: joincondition = ( getattr(source_type, self.relation.linkage.relation.foreignkeycol) == target_type.get_primary_key_attr() ) else: joincondition = getattr(source_type, source_type.get_primary_key_attr_name()) == getattr( xref_object, self.relation.linkage.relation.foreignkeycol ) query = query.outerjoin((source_type, joincondition)) # Since the the source table's primary key is either filled for linked elements or None for unlinked, this simple condition to find out what is linked to ourselves is sufficient. # Unlinked entries won't match since their source primary key field will be None. query = query.add_column( func.max( case( [ ( getattr(source_type, source_type.get_primary_key_attr_name()) == self.relation_source.id, "true", ) ], else_="false", ) ).label("linked") ) # For 1:n/1:1(fk), don't allow entries linked to someone else to show up (since they cannot have their foreign key point at two things). if xref_object == None and ( self.relation.linkage.cardinality.id == "ONE_TO_MANY" or self.relation.linkage.cardinality.id == "ONE_TO_ONE(FK)" ): query = query.filter( or_( getattr(source_type, source_type.get_primary_key_attr_name()) == self.relation_source.id, getattr(source_type, source_type.get_primary_key_attr_name()) == None, ) ) # Group query query = query.group_by(target_type.get_primary_key_attr()) else: if query_mode == QueryMode.EXCLUSIVE: # Inner join should be sufficient if xref_object is None: # The join condition is also explicitely required here for cases with many relations to the same table if self.relation.linkage.cardinality.id == "ONE_TO_MANY": query = session.query(target_type).join( ( source_type, source_type.get_primary_key_attr() == getattr(target_type, self.relation.linkage.relation.foreignkeycol), ) ) else: query = session.query(target_type).join( ( source_type, target_type.get_primary_key_attr() == getattr(source_type, self.relation.linkage.relation.foreignkeycol), ) ) else: # n:m, we need to specify the join condition: query = session.query(target_type).join( ( xref_object, target_type.id == getattr(xref_object, self.relation.linkage.relation.foreignkeycol2), ) ) query = query.join( ( source_type, and_( source_type.id == getattr(xref_object, self.relation.linkage.relation.foreignkeycol), source_type.id == self.relation_source.get_primary_key_attr(), ), ) ) elif query_mode == QueryMode.WITH_UNLINKED: # we require a full outer join if xref_object is None: query = session.query(target_type).outerjoin(source_type) else: # n:m, we need to specify the join condition: query = session.query(target_type).outerjoin( ( xref_object, target_type.id == getattr(xref_object, self.relation.linkage.relation.foreignkeycol2), ) ) query = query.join( ( source_type, or_( and_( source_type.id == getattr(xref_object, self.relation.linkage.relation.foreignkeycol), source_type.id == self.relation_source.get_primary_key_attr(), ), source_type.id == None, ), ) ) if xref_object is None: if self.relation.linkage.cardinality.id == "ONE_TO_MANY": # Foreignkey on target_type side foreignkey_attr = getattr(target_type, self.relation.linkage.relation.foreignkeycol) else: # Foreignkey on source_type side foreignkey_attr = getattr(source_type, self.relation.linkage.relation.foreignkeycol) query = query.add_column(case([(foreignkey_attr == None, "false")], else_="true").label("linked")) if query_mode == QueryMode.WITH_UNLINKED: query = query.filter( or_(source_type.get_primary_key_attr() == self.relation_source.id, foreignkey_attr == None) ) else: # n:m relation foreignkeycolumn1 = getattr(xref_object, self.relation.linkage.relation.foreignkeycol) foreignkeycolumn2 = getattr(xref_object, self.relation.linkage.relation.foreignkeycol2) query = query.add_column( case([((or_(foreignkeycolumn1 == None, foreignkeycolumn2 == None)), "false")], else_="true").label( "linked" ) ) if query_mode == QueryMode.WITH_UNLINKED: query = query.filter( or_( source_type.get_primary_key_attr() == self.relation_source.id, foreignkeycolumn1 == None, foreignkeycolumn2 == None, ) ) if query_mode == QueryMode.EXCLUSIVE: query = query.filter( getattr(source_type, source_type.get_primary_key_attr_name()) == self.relation_source.id ) # Check for additional constraints on relation widget if ( hasattr(self.relation, "filter_clause") and self.relation.filter_clause != None and len(self.relation.filter_clause) > 0 ): query = query.filter(self.relation.filter_clause) return query
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
def process_object(self, node, parent_setobject): action = node.get('action') if not action: raise SetobjectGraphException("Mandatory action attribute missing.") typename = node.get('type') klass = setobject_type_registry.lookup(typename) objid = node.get('objid') linked = node.get('linked') setobject = None if action == 'new' and node.getparent().tag == 'coll': attr_name = node.getparent().get('attr_name') linkage = parent_setobject.collections[attr_name]['linkage'] if not linkage.use_list: if linked == 'true' and \ getattr(parent_setobject, attr_name, None) != None: setobject = getattr(parent_setobject, attr_name) setobject.id = objid else: refkey = linkage.ref_key coll = getattr(parent_setobject, attr_name) key = None if refkey == None: key = node.get('objid') else: for prop in node: if prop.get('name') == refkey: key = prop.text break; assert(key != None) if key in coll: setobject = coll[key] setobject.id = objid if setobject == None: if action == 'save': setobject = self.session.query(klass).filter(klass.get_primary_key_attr() == objid).one() self.session.add(setobject) notify(ObjectCreatedEvent(setobject)) self.session.flush() elif action == 'new': assert(self.session.query(klass).get(objid) is None) setobject = klass() setobject.id = objid self.session.add(setobject) self.session.flush() elif action == 'delete': setobject = self.session.query(klass).filter(klass.get_primary_key_attr() == objid).one() # Actual deletion is performed as post order step as it may be necessary # to clear linkages prior deleting the object. setobject = self.session.query(klass).filter(klass.get_primary_key_attr() == objid).one() else: raise SetobjectGraphException("Invalid action '" + action + "' for setobject", node.get('objid')) self.do_linkage(node, setobject, parent_setobject) if action != 'delete': setobject.pre_order_traverse() setobject = self.session.query(klass).get(objid) assert(setobject != None) if action == 'delete': # Don't need to traverse deeper in tree. descend = False else: descend = True return setobject, descend
def create_widget(cls, widget_type): widget_type = setobject_type_registry.lookup(widget_type) widget = widget_type() return widget
def do(self, plan, searchterm, group, page, resultsperpage, uservars=[]): """ Do a search on the plan based on a generic search term and return the results. The results will also be associated with information about which fields actually matched the search query and whether there is a next page to the current one. Please note this implementation is most likely SLOW and could need optimization or replacement at some point. """ dbutility = getUtility(IDbUtility) # change searchterm into LIKE compatible syntax searchterm = self.replaceoperators(searchterm) # list to hold the search values/columns we collect from the widgets searchvalues = [] # collect all columns based on the widgets on the form and their mapping for form in plan.forms.itervalues(): for widget in form.widgets.itervalues(): if widget.widget_type == 'relation' or \ widget.widget_type == 'fileupload' or \ widget.widget_type == 'dropdown': continue for span in widget.spans.itervalues(): if hasattr(span, 'attr_name') and span.attr_name != None: # We got a new column to examine. if span.attr_name != 'span_value' and len(span.attr_name) > 0: self.addsearchvalue(searchvalues, span.attr_name, widget.widget_identifier, form.form_identifier) # do we have some columns to search through? #if len(searchvalues) <= 0: # return {'resultset' : None, 'searchfields' : None, 'nextpage': False} # nothing to search for! # get the table class object tableclass = setobject_table_registry.lookup_by_table(plan.table_identifier) # lists for composing the conditions/columns used in our query conditions = [] columns = [] # we always want to have the primary key column in our results klass = setobject_type_registry.lookup(plan.klass) columns.append(getattr(tableclass.c, klass.get_primary_key_attr_name())) # compose the search conditions based on the avilable input fields for value in searchvalues: if searchterm != '%': condition = getattr(tableclass.c, value['field']).like(searchterm, escape='\\') else: condition1 = getattr(tableclass.c, value['field']).like(searchterm, escape='\\') condition2 = (getattr(tableclass.c, value['field']) == None) condition = or_(condition1, condition2) conditions.append(condition) columns.append(getattr(tableclass.c, value['field'])) columns.append(condition.label("_field_matched_" + value['field'])) # compose our query if len(conditions) > 0: queryobj = select(columns).where(or_(*conditions)).offset((int(page)-1) * resultsperpage).limit(resultsperpage+1) else: queryobj = select(columns).offset((int(page)-1) * resultsperpage).limit(resultsperpage+1) # See if there is a next page to this one gotnextpage = False resultarray = [] results = queryobj.execute() for result in results: if len(resultarray) < resultsperpage: resultarray.append(result) else: gotnextpage = True return {'resultset' : resultarray, 'searchfields' : searchvalues, 'nextpage' : gotnextpage}
def create_span(cls, span_type_name, span_name): span_type = setobject_type_registry.lookup(span_type_name) return span_type(span_name)