Пример #1
0
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()
Пример #2
0
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)
Пример #3
0
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'])
Пример #4
0
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),
    })
Пример #5
0
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),
    })