def get_column(self, column): if "." in column.model_name: column_path = column.model_name.split(".") # get the column we are getting column_name = column_path[-1] # the path to the column column_path = column_path[:-1] curmodel = self.model for column in column_path: curmodel = helpme.get_related_model(curmodel, column) model_column = getattr(curmodel, column_name) else: model_column = getattr(self.model, column.model_name) return model_column
def __init__(self, params, model, query, columns, total_recs=0): self.params = params self.model = model self.query = query self.data = {} self.columns = [] self.columns_dict = {} self.total_recs = total_recs for col in columns: name, model_name, filter_func = None, None, None if isinstance(col, DataColumn): d = col self.columns.append(d) elif isinstance(col, tuple): # col is either 1. (name, model_name), 2. (name, filter) or 3. (name, model_name, filter) if len(col) == 3: name, model_name, filter_func = col elif len(col) == 2: # Work out the second argument. If it is a function then it's type 2, else it is type 1. if callable(col[1]): name, filter_func = col model_name = name else: name, model_name = col else: raise ValueError( "Columns must be a tuple of 2 to 3 elements") d = DataColumn(name=name, model_name=model_name, filter=filter_func) self.columns.append(d) else: # It's just a string name, model_name = col, col d = DataColumn(name=name, model_name=model_name, filter=None) self.columns.append(d) self.columns_dict[d.name] = d # get only unique relationships to join # fix for when there are multiple columns within the same joined table # only eliminates warnings but still... seenjoins = [] seencols = [] for column in (col for col in self.columns if "." in col.model_name): # of of table user model_name can look like family.address.city or more/less dots # joincols would be ['family', 'address'] leaving out the actual column, city log_debug("column: {}".format(column)) joincols = column.model_name.split(".")[:-1] log_debug("joincols: {}".format(joincols)) curtable = helpme.get_related_model(self.model, joincols[0]).__tablename__ log_debug("curtable: {}, joincols: {}".format(curtable, joincols)) # join the first column, which is off of our class # check if 'family' is joined already if joincols[0] not in seencols and curtable not in seenjoins: seenjoins.append(curtable) log_debug("seenjoins is now: {}".format(seenjoins)) # append family to seencols so we don't rejoin later log_debug("appending {} to seencols".format(joincols[0])) seencols.append(joincols[0]) # outer join family log_debug("joincols[0] is {}".format(joincols[0])) self.query = self.query.join(joincols[0], isouter=True) log_debug("query is now: {}".format(self.query)) # check if we are doing more than the simple user.famly join (in this example user.family.address) if len(joincols) > 1: # copy our table to curmodel curmodel = self.model log_debug("curmodel is now: {}".format(curmodel.__tablename__)) # we don't want to do this to the last item ([:-1]) for i, joincol in enumerate(joincols[:-1]): # helper method to get the table for the current related model curmodel = helpme.get_related_model(curmodel, joincol) log_debug("i -> {}, joincol -> {}".format(i, joincol)) # we don't want to do this for columns we already did also if joincol not in seencols: log_debug("joincol not in seencols: {}, {}".format( joincol, seencols)) seencols.append(joincol) if joincols[i + 1] not in seencols: log_debug( "joincols[i+1] not in seencols: {}, {}".format( joincols[i + 1], seencols)) # get the tablename so we can log that we joined with it joinmodel = aliased( helpme.get_related_model(curmodel, joincols[i + 1])) if joinmodel.__tablename__ in seenjoins: continue # append to seen joins seenjoins.append(joinmodel.__tablename__) # get the remote table object like User.domus rather than XenDomU like above aliased will pull out joinmodel = getattr(curmodel, joincols[i + 1]) log_debug("joinmodel: {}".format(joinmodel)) #self.query = self.query.join(getattr(curmodel, joincols[i+1]), isouter=True) self.query = self.query.join(joinmodel, isouter=True) seencols.append(joincols[i + 1]) log_debug(str(self.query))
def __init__(self, params, model, query, columns): self.params = params self.model = model self.query = query self.data = {} self.columns = [] self.columns_dict = {} for col in columns: name, model_name, filter_func = None, None, None if isinstance(col, DataColumn): d = col self.columns.append(d) elif isinstance(col, tuple): # col is either 1. (name, model_name), 2. (name, filter) or 3. (name, model_name, filter) if len(col) == 3: name, model_name, filter_func = col elif len(col) == 2: # Work out the second argument. If it is a function then it's type 2, else it is type 1. if callable(col[1]): name, filter_func = col model_name = name else: name, model_name = col else: raise ValueError("Columns must be a tuple of 2 to 3 elements") d = DataColumn(name=name, model_name=model_name, filter=filter_func) self.columns.append(d) else: # It's just a string name, model_name = col, col d = DataColumn(name=name, model_name=model_name, filter=None) self.columns.append(d) self.columns_dict[d.name] = d # get only unique relationships to join # fix for when there are multiple columns within the same joined table # only eliminates warnings but still... seenjoins = [] seencols = [] for column in (col for col in self.columns if "." in col.model_name): # of of table user model_name can look like family.address.city or more/less dots # joincols would be ['family', 'address'] leaving out the actual column, city log_debug("column: {}".format(column)) joincols = column.model_name.split(".")[:-1] log_debug("joincols: {}".format(joincols)) curtable = helpme.get_related_model(self.model, joincols[0]).__tablename__ log_debug("curtable: {}, joincols: {}".format(curtable, joincols)) # join the first column, which is off of our class # check if 'family' is joined already if joincols[0] not in seencols and curtable not in seenjoins: seenjoins.append(curtable) log_debug("seenjoins is now: {}".format(seenjoins)) # append family to seencols so we don't rejoin later log_debug("appending {} to seencols".format(joincols[0])) seencols.append(joincols[0]) # outer join family log_debug("joincols[0] is {}".format(joincols[0])) self.query = self.query.join(joincols[0], isouter=True) log_debug("query is now: {}".format(self.query)) # check if we are doing more than the simple user.famly join (in this example user.family.address) if len(joincols) > 1: # copy our table to curmodel curmodel = self.model log_debug("curmodel is now: {}".format(curmodel.__tablename__)) # we don't want to do this to the last item ([:-1]) for i, joincol in enumerate(joincols[:-1]): # helper method to get the table for the current related model curmodel = helpme.get_related_model(curmodel, joincol) log_debug("i -> {}, joincol -> {}".format(i, joincol)) # we don't want to do this for columns we already did also if joincol not in seencols: log_debug("joincol not in seencols: {}, {}".format(joincol, seencols)) seencols.append(joincol) if joincols[i + 1] not in seencols: log_debug("joincols[i+1] not in seencols: {}, {}".format(joincols[i + 1], seencols)) # get the tablename so we can log that we joined with it joinmodel = aliased(helpme.get_related_model(curmodel, joincols[i + 1])) if joinmodel.__tablename__ in seenjoins: continue # append to seen joins seenjoins.append(joinmodel.__tablename__) # get the remote table object like User.domus rather than XenDomU like above aliased will pull out joinmodel = getattr(curmodel, joincols[i + 1]) log_debug("joinmodel: {}".format(joinmodel)) # self.query = self.query.join(getattr(curmodel, joincols[i+1]), isouter=True) self.query = self.query.join(joinmodel, isouter=True) seencols.append(joincols[i + 1]) log_debug(str(self.query))