def trim_column_names(apps, schema_editor): """ Traverse all workshops and trim column names to 63 characters. :param apps: :param schema_editor: :return: """ for wflow in Workflow.objects.all(): rename_cols = [] for column in wflow.columns.all(): if len(column.name) <= 63: continue rename_cols.append(column) if not rename_cols: continue new_names = _make_unique_new_names( [col.name[:63] for col in rename_cols]) for col, new_name in zip(rename_cols, new_names): if col.name[:63] == new_name: continue db_rename_column( wflow.get_data_frame_table_name(), col.name[:63], new_name) col.name = new_name col.save()
def update_column( user, workflow: models.Workflow, column: models.Column, old_name: str, old_position: int, action_column_item: Optional[models.Action] = None, action_column_event: Optional[str] = None, ): """Update information in a column. :param user: User performing the operation :param workflow: Workflow being processed :param column: Column being modified :param old_name: Old name to detect renaming :param old_position: old position to detect repositioning :param action_column_item: Action/column item in case the action is stored in that table. :param action_column_event: Event to record the operation on the action/column :return: Nothing. Side effect in the workflow. """ # If there is a new name, rename the data frame columns if old_name != column.name: sql.db_rename_column( workflow.get_data_frame_table_name(), old_name, column.name) pandas.rename_df_column(workflow, old_name, column.name) if old_position != column.position: # Update the positions of the appropriate columns workflow.reposition_columns(old_position, column.position) column.save() # Go back to the DB because the prefetch columns are not valid # any more workflow = models.Workflow.objects.prefetch_related('columns').get( id=workflow.id, ) # Changes in column require rebuilding the query_builder_ops workflow.set_query_builder_ops() # Save the workflow workflow.save() if action_column_item: action_column_item.log(user, action_column_event) # Log the event column.log(user, models.Log.COLUMN_EDIT)
def store_workflow_table( workflow, update_info: Optional[Dict] = None, ): """Make a temporary DB table the workflow table. It is assumed that there is a temporal table already in the database. The function performs the following steps: Step 1: Drop the columns that are not being uploaded Step 2: Rename the columns (if needed) Step 3: Create the workflow columns Step 4: Rename the table (temporary to final) Step 5: Update workflow fields and update :param workflow: Workflow object being manipulated. :param update_info: Dictionary with the following fields: - initial_column_names: list of column names detected in read phase. - rename_column_names: List of new names for the columns - column_types: List of types detected after storing in DB - keep_key_column: List of booleans to flag if key property is kept - columns_to_upload: List of booleans to flag column upload The first field is mandatory. The have default values if not provided. :return: Nothing. Anomalies are raised as Exceptions """ # Check information on update_info and complete if needed if not update_info.get('initial_column_names'): raise _('Internal error while processing database.') if not update_info.get('rename_column_names'): update_info['rename_column_names'] = update_info[ 'initial_column_names'] if not update_info.get('column_types'): raise _('Internal error while processing database.') if not update_info.get('keep_key_column'): raise _('Internal error while processing database.') if not update_info.get('columns_to_upload'): update_info['columns_to_upload'] = [True] * len( update_info['initial_column_names']) db_table = workflow.get_upload_table_name() new_columns = [] for old_n, new_n, data_type, is_key, upload in zip( update_info['initial_column_names'], update_info['rename_column_names'], update_info['column_types'], update_info['keep_key_column'], update_info['columns_to_upload'], ): # Detect if the column is new or already exists current_col = workflow.columns.filter(name=old_n).first() # Step 1: Check if column needs to be uploaded if not upload: # Column is dropped sql.df_drop_column(db_table, old_n) if current_col: # Dropping an existing column. Incorrect. raise _('Invalid column drop operation.') continue # Step 2: Check if the column must be renamed if old_n != new_n: # Rename column from old_n to new_n sql.db_rename_column(db_table, old_n, new_n) if current_col: rename_df_column(workflow, old_n, new_n) if current_col: if current_col.data_type != data_type: # If the column type in the DB is different from the one in the # object, update current_col.data_type = data_type current_col.save() else: # Step 3: Create the column new_columns.append((new_n, data_type, is_key)) # Create the columns workflow.add_columns(new_columns) workflow.refresh_from_db() # Step 4: Rename the table (Drop the original one first if workflow.has_table(): sql.delete_table(workflow.get_data_frame_table_name()) sql.rename_table(db_table, workflow.get_data_frame_table_name()) # Step 5: Update workflow fields and save workflow.nrows = sql.get_num_rows(workflow.get_data_frame_table_name()) workflow.set_query_builder_ops() workflow.save(update_fields=['nrows', 'query_builder_ops'])
def column_edit( request: HttpRequest, pk: int, workflow: Optional[Workflow] = None, column: Optional[Column] = None, ) -> JsonResponse: """Edit a column. :param request: :param pk: :return: """ # Detect if this operation is to edit a new column or a new question (in # the edit in page) is_question = 'question_edit' in request.path_info # Form to read/process data if is_question: form = QuestionRenameForm(request.POST or None, workflow=workflow, instance=column) else: form = ColumnRenameForm(request.POST or None, workflow=workflow, instance=column) if request.method == 'POST' and form.is_valid(): if not form.has_changed(): return JsonResponse({'html_redirect': None}) # Some field changed value, so save the result, but # no commit as we need to propagate the info to the df column = form.save(commit=False) # If there is a new name, rename the data frame columns if form.old_name != form.cleaned_data['name']: db_rename_column(workflow.get_data_frame_table_name(), form.old_name, column.name) rename_df_column(workflow, form.old_name, column.name) if form.old_position != form.cleaned_data['position']: # Update the positions of the appropriate columns workflow.reposition_columns(form.old_position, column.position) # Save the column information column.save() # Go back to the DB because the prefetch columns are not valid # any more workflow = Workflow.objects.prefetch_related('columns').get( id=workflow.id, ) # Changes in column require rebuilding the query_builder_ops workflow.set_query_builder_ops() # Save the workflow workflow.save() # Log the event if is_question: event_type = Log.QUESTION_ADD else: event_type = Log.COLUMN_ADD Log.objects.register(request.user, event_type, workflow, { 'id': workflow.id, 'name': workflow.name, 'column_name': column.name }) # Done processing the correct POST request return JsonResponse({'html_redirect': ''}) if is_question: template = 'workflow/includes/partial_question_addedit.html' else: template = 'workflow/includes/partial_column_addedit.html' return JsonResponse({ 'html_form': render_to_string(template, { 'form': form, 'cname': column.name, 'pk': pk }, request=request), })
def criterion_edit( request: HttpRequest, pk: int, workflow: Optional[Workflow] = None, ) -> JsonResponse: """Edit a criterion in a rubric. :param request: :param pk: For the Action/Column/condition triplet :return: JSON Response """ triplet = ActionColumnConditionTuple.objects.filter(pk=pk).first() if not triplet: messages.error( request, _('Incorrect invocation of criterion edit function') ) return JsonResponse({'html_redirect': ''}) action = triplet.action column = triplet.column form = CriterionForm( request.POST or None, workflow=workflow, other_criterion=ActionColumnConditionTuple.objects.filter( action=action ).exclude(column=column.id).first(), instance=column) if request.method == 'POST' and form.is_valid(): if not form.has_changed(): return JsonResponse({'html_redirect': None}) # Some field changed value, so save the result, but # no commit as we need to propagate the info to the df column = form.save(commit=False) # If there is a new name, rename the data frame columns if form.old_name != form.cleaned_data['name']: db_rename_column( workflow.get_data_frame_table_name(), form.old_name, column.name) rename_df_column(workflow, form.old_name, column.name) if form.old_position != form.cleaned_data['position']: # Update the positions of the appropriate columns workflow.reposition_columns(form.old_position, column.position) # Save the column information column.save() # Go back to the DB because the prefetch columns are not valid # any more workflow = Workflow.objects.prefetch_related('columns').get( id=workflow.id, ) # Changes in column require rebuilding the query_builder_ops workflow.set_query_builder_ops() # Save the workflow workflow.save() # Log the event triplet.log(request.user, Log.ACTION_RUBRIC_CRITERION_EDIT) # Done processing the correct POST request return JsonResponse({'html_redirect': ''}) return JsonResponse({ 'html_form': render_to_string( 'workflow/includes/partial_criterion_addedit.html', {'form': form, 'cname': column.name, 'pk': pk}, request=request), })