def post(self, request): """ HttpResponseRedirect: For valid POST requests the client will be redirected to the appropriate data view. """ formclasses = construct_forms(self.experiment_model) app_label = self.experiment_model._meta.app_label formset_list = [] for formclass in formclasses: FormSetClass = formset_factory(formclass.classname, max_num=formclass.classname.max_num) formset_list.append(FormSetClass(request.POST, prefix=formclass.prefix)) # Validation for formset in formset_list: if not formset.is_valid(): validated = False break else: validated = True continue if validated: requested_exps = get_requested_experiments(formset_list, self.experiment_model) id_str = get_id_str(requested_exps) url = '/{}/data/{}/'.format(app_label, id_str) return redirect(url) # If not validated... else: formset_list = [] # Instantiate formsets with prefix and POST data. for formclass in formclasses: FormSetClass = formset_factory(formclass.classname, max_num=formclass.classname.max_num) # Check whether POST contains data for this specific formset. has_data = False for pkey in request.POST.keys(): if pkey.startswith(formclass.prefix + '-0-'): if request.POST.get(pkey): has_data = True break else: continue # If there is data instantiate with POST data, # else instantiate empty formset ## This is done, because forms completely removed with JS ## do not show up again otherwise if has_data: formset_list.append(FormSetClass(request.POST, prefix=formclass.prefix)) else: formset_list.append(FormSetClass(prefix=formclass.prefix)) context = {'formset_list': formset_list, 'subheader': 'Filter'} return render(request, 'disbi/filter.html', context)
def get_exp_columns(self, wanted_exps): """ Get column of respective experiment. """ # Get the dict. exp_id_str = get_id_str(self.req_exps) table_name = '%s_datatable_%s' % (self.app_label, exp_id_str) # Make experiment unique. if not db_table_exists(table_name): self.create_base_table(table_name) column_names = list(get_columnnames(table_name)) divisor_col = None dividend_col = None #exp_cols = [] #potential_columns = [] # Iterate over all column names, and make a list of those that hold data. datacol_pattern = re.compile(r'_\d+$') dividend_pattern = r'_{}$'.format(str(wanted_exps['dividend'].id)) divisor_pattern = r'_{}$'.format(str(wanted_exps['divisor'].id)) for column_name in column_names: if datacol_pattern.search(column_name) is not None: if divisor_col is None: if re.search(divisor_pattern, column_name): divisor_col = column_name if dividend_col is None: if re.search(dividend_pattern, column_name): dividend_col = column_name sql = "SELECT %s, %s FROM %s;" % (dividend_col, divisor_col, table_name) return from_db(sql, fetch_as='tuple')
def get_or_create_base_table(self, fetch_as='ordereddict'): """ Retrieve the base table from the DB. Create it if it does not exist. Returns: The values fetched from the DB. """ # Make a sorted list of all ids. exp_id_str = get_id_str(self.req_exps) table_name = '%s_%s_%s' % ( self.app_label, settings.DISBI['DATATABLE_PREFIX'], exp_id_str) if not db_table_exists(table_name): self.create_base_table(table_name) column_names = list(get_columnnames(table_name)) # Escape all column names. column_names = ['%s' % column_name for column_name in column_names] # Format all columns with scientific notation that end with underscore and a number. # These columns contain numerical data and should be presented in # scientific notation. datacol_pattern = re.compile(r'_\d+$') for i, column_name in enumerate(column_names): if datacol_pattern.search(column_name) is not None: column_names[i] = '{} as {}'.format( self.wrap_in_func('to_char', column_name, self.DB_PRECISION), column_name) sql = 'SELECT %s FROM %s' % (', '.join(column_names), table_name) #return from_db(sql) return from_db(sql, fetch_as=fetch_as)
def test_get_id_str(self): ids = [5, 3, 7, 1] model_objs = [] for identifier in ids: mock_model = SimpleNamespace() mock_model.id = identifier model_objs.append(deepcopy(mock_model)) self.assertEqual('1_3_5_7', get_id_str(model_objs))
def add_foldchange(self, exps_for_fc, fetch_as='ordereddict'): """ Add the fold change to a base table. """ exp_id_str = get_id_str(self.req_exps) table_name = '%s_datatable_%s' % (self.app_label, exp_id_str) # Make experiment for fold change unique. exps_for_fc = get_unique(exps_for_fc) if not db_table_exists(table_name): self.create_base_table(table_name) column_names = list(get_columnnames(table_name)) # Inititialize lists. dividend = [None] * len(exps_for_fc) divisor = [None] * len(exps_for_fc) fc_col_position = [None] * len(exps_for_fc) # Format all columns with scientific notation that end with underscore and a number. datacol_pattern = re.compile(r'_\d+$') for i, column_name in enumerate(column_names): if datacol_pattern.search(column_name) is not None: column_names[i] = '{} AS {}'.format( self.wrap_in_func('to_char', column_name, self.DB_PRECISION), column_name) for j, pair in enumerate(exps_for_fc): pattern = r'_{}$'.format(str(pair['dividend'].id)) if re.search(pattern, column_name): if not dividend[j]: dividend[j] = ( column_name, pair['dividend'].id, ) # For the j-th column there will be j columns inserted before that. fc_col_position[j] = i + j elif (str(pair['divisor'].id) in column_name and not divisor[j]): divisor[j] = (column_name, pair['divisor'].id) # Insert the columns for calculating the fold change. for i in range(len(dividend)): fc_col = '{quotient} AS {quotient_name}'.format( quotient=self.wrap_in_func( 'to_char', self.wrap_in_func(self.DB_FUNCTION_ZERO, dividend[i][0], divisor[i][0]), self.DB_PRECISION), quotient_name='"fc_%s_%s"' % (dividend[i][1], divisor[i][1]), ) column_names.insert(fc_col_position[i], fc_col) sql = "SELECT %s FROM %s" % (', '.join(column_names), table_name) return from_db(sql, fetch_as=fetch_as)