def create(self, validated_data, **kwargs): # Preliminary checks data_type = validated_data.get('data_type', None) if data_type is None or \ data_type not in pandas_datatype_names.values(): # The data type is not legal raise Exception(_('Incorrect data type {0}.').format(data_type)) column_obj = None try: # Create the object, but point to the given workflow column_obj = Column( name=validated_data['name'], description_text=validated_data.get('description_text', ''), workflow=self.context['workflow'], data_type=data_type, is_key=validated_data.get('is_key', False), position=validated_data.get('position', 0), in_viz=validated_data.get('in_viz', True), active_from=validated_data.get('active_from', None), active_to=validated_data.get('active_to', None), ) # Set the categories if they exists column_obj.set_categories(validated_data.get('categories', []), True) if column_obj.active_from and column_obj.active_to and \ column_obj.active_from > column_obj.active_to: raise Exception( _('Incorrect date/times in the active window for ' 'column {0}').format(validated_data['name'])) # TODO: Fix the position field when creating the columns # All tests passed, proceed to save the object. column_obj.save() except Exception as e: if column_obj: column_obj.delete() raise e return column_obj
def workflow_delete_column( workflow: Workflow, column: Column, cond_to_delete: Optional[List[Condition]] = None, ): """Remove column from workflow. Given a workflow and a column, removes it from the workflow (and the corresponding data frame :param workflow: Workflow object :param column: Column object to delete :param cond_to_delete: List of conditions to delete after removing the column :return: Nothing. Effect reflected in the database """ # Drop the column from the DB table storing the data frame df_drop_column(workflow.get_data_frame_table_name(), column.name) # Reposition the columns above the one being deleted workflow.reposition_columns(column.position, workflow.ncols + 1) # Delete the column column.delete() # Update the information in the workflow workflow.ncols = workflow.ncols - 1 workflow.save() if not cond_to_delete: # The conditions to delete are not given, so calculate them # Get the conditions/actions attached to this workflow cond_to_delete = [ cond for cond in Condition.objects.filter(action__workflow=workflow, ) if column in cond.columns.all() ] # If a column disappears, the conditions that contain that variable # are removed actions_without_filters = [] for condition in cond_to_delete: if condition.is_filter: actions_without_filters.append(condition.action) # Formula has the name of the deleted column. Delete it condition.delete() # Traverse the actions for which the filter has been deleted and reassess # all their conditions # TODO: Explore how to do this asynchronously (or lazy) map(lambda act: act.update_n_rows_selected(), actions_without_filters) # If a column disappears, the views that contain only that column need to # disappear as well as they are no longer relevant. for view in workflow.views.all(): if view.columns.count() == 0: view.delete()