Пример #1
0
def row_update(
    request: HttpRequest,
    workflow: Optional[models.Workflow] = None,
) -> HttpResponse:
    """Process POST request to update a row in the data table.

    :param request: Request object with all the data.
    :param workflow: Workflow being manipulated
    :return: Http Response with the page rendering.
    """
    # Get the pair key,value to fetch the row from the table
    update_key = request.GET.get('k')
    update_val = request.GET.get('v')

    if not update_key or not update_val:
        # Malformed request
        return render(request, 'error.html',
                      {'message': _('Unable to update table row')})

    # Get the form populated with the row values
    form = forms.RowForm(request.POST or None,
                         workflow=workflow,
                         initial_values=sql.get_row(
                             workflow.get_data_frame_table_name(),
                             key_name=update_key,
                             key_value=update_val,
                             column_names=workflow.get_column_names()))

    if request.method == 'POST' and form.is_valid():
        if not form.has_changed():
            return redirect('table:display')

        try:
            row_values = [
                form.cleaned_data[(ONTASK_UPLOAD_FIELD_PREFIX + '%s') % idx]
                for idx in range(workflow.columns.count())
            ]
            services.update_row_values(workflow, update_key, update_val,
                                       row_values)
        except Exception as exc:
            form.add_error(None, str(exc))
            return render(
                request, 'dataops/row_filter.html', {
                    'workflow': workflow,
                    'form': form,
                    'cancel_url': reverse('table:display')
                })

        workflow.log(request.user,
                     models.Log.WORKFLOW_DATA_ROW_UPDATE,
                     new_values=list(
                         zip([col.name for col in workflow.columns.all()],
                             [str(rval) for rval in row_values])))
        return redirect('table:display')

    return render(request, 'dataops/row_filter.html', {
        'workflow': workflow,
        'form': form,
        'cancel_url': reverse('table:display')
    })
Пример #2
0
def get_row_values(
    action: models.Action,
    row_idx: Union[int, Tuple[str, str]],
) -> Dict[str, Union[str, int, float, datetime]]:
    """Get the values in a row either by index or by key.

    Given an action and a row index, obtain the appropriate row of values
    from the data frame.

    :param action: Action object
    :param row_idx: Row index to use for evaluation
    :return Dictionary with the data row
    """
    # Step 1: Get the row of data from the DB
    filter_formula = action.get_filter_formula()

    # If row_idx is an integer, get the data by index, otherwise, by key
    if isinstance(row_idx, int):
        row = pandas.get_table_row_by_index(
            action.workflow,
            filter_formula,
            row_idx,
        )
    else:

        row = sql.get_row(
            action.workflow.get_data_frame_table_name(),
            row_idx[0],
            row_idx[1],
            column_names=action.workflow.get_column_names(),
            filter_formula=filter_formula,
        )
    return row
    def test_row_create(self):
        """Test the view to filter items."""
        nrows = self.workflow.nrows

        # Row create (GET)
        resp = self.get_response('dataops:rowcreate')
        self.assertTrue(status.is_success(resp.status_code))

        # Row create POST
        resp = self.get_response('dataops:rowcreate',
                                 method='POST',
                                 req_params={
                                     '___ontask___upload_0': '8',
                                     '___ontask___upload_1': 'text1',
                                     '___ontask___upload_2': 'text2',
                                     '___ontask___upload_3': '12.1',
                                     '___ontask___upload_4': '12.2',
                                     '___ontask___upload_5': 'on',
                                     '___ontask___upload_6': '',
                                     '___ontask___upload_7':
                                     '06/07/2019 19:32',
                                     '___ontask___upload_8': '06/05/2019 19:23'
                                 })
        self.assertTrue(status.is_success(resp.status_code))

        # Update the workflow
        self.workflow.refresh_from_db()
        self.assertEqual(nrows, self.workflow.nrows)

        # Row create POST
        resp = self.get_response('dataops:rowcreate',
                                 method='POST',
                                 req_params={
                                     '___ontask___upload_0': '9',
                                     '___ontask___upload_1': 'text add 1',
                                     '___ontask___upload_2': 'text add 2',
                                     '___ontask___upload_3': '22',
                                     '___ontask___upload_4': '23',
                                     '___ontask___upload_5': 'on',
                                     '___ontask___upload_7':
                                     '06/07/2019 19:32',
                                     '___ontask___upload_8': '06/05/2019 19:23'
                                 })
        self.assertEqual(resp.status_code, status.HTTP_302_FOUND)

        # Update the workflow
        self.workflow.refresh_from_db()
        self.assertEqual(nrows + 1, self.workflow.nrows)

        row_val = get_row(self.workflow.get_data_frame_table_name(),
                          key_name='key',
                          key_value=9)
        self.assertEqual(row_val['text1'], 'text add 1')
        self.assertEqual(row_val['text2'], 'text add 2')
        self.assertEqual(row_val['double1'], 22)
        self.assertEqual(row_val['double2'], 23)
    def test_row_edit(self):
        """Test the view to filter items."""
        nrows = self.workflow.nrows

        # Row edit (GET)
        resp = self.get_response('dataops:rowupdate',
                                 req_params={
                                     'k': 'key',
                                     'v': '8'
                                 })
        self.assertTrue(status.is_success(resp.status_code))
        self.assertTrue('Edit learner data' in str(resp.content))

        # Get the GET URL with the paramegters
        request = self.factory.get(reverse('dataops:rowupdate'), {
            'k': 'key',
            'v': '8'
        })

        request = self.factory.post(
            request.get_full_path(), {
                '___ontask___upload_0': '8',
                '___ontask___upload_1': 'NEW TEXT 1',
                '___ontask___upload_2': 'NEW TEXT 2',
                '___ontask___upload_3': '111',
                '___ontask___upload_4': '222',
                '___ontask___upload_5': 'on',
                '___ontask___upload_6': '',
                '___ontask___upload_7': '06/07/2019 19:32',
                '___ontask___upload_8': '06/05/2019 19:23'
            })
        request = self.add_middleware(request)
        resp = row_update(request)
        self.assertEqual(resp.status_code, status.HTTP_302_FOUND)

        row_val = get_row(self.workflow.get_data_frame_table_name(),
                          key_name='key',
                          key_value=8)

        self.assertEqual(row_val['text1'], 'NEW TEXT 1')
        self.assertEqual(row_val['text2'], 'NEW TEXT 2')
        self.assertEqual(row_val['double1'], 111)
        self.assertEqual(row_val['double2'], 222)
Пример #5
0
def row_update(
    request: HttpRequest,
    workflow: Optional[Workflow] = None,
) -> HttpResponse:
    """Process POST request to update a row in the data table.

    :param request: Request object with all the data.

    :return:
    """
    # Get the pair key,value to fetch the row from the table
    update_key = request.GET.get('k')
    update_val = request.GET.get('v')

    if not update_key or not update_val:
        # Malformed request
        return render(request, 'error.html',
                      {'message': _('Unable to update table row')})

    # Get the form populated with the row values
    form = RowForm(request.POST or None,
                   workflow=workflow,
                   initial_values=get_row(
                       workflow.get_data_frame_table_name(),
                       key_name=update_key,
                       key_value=update_val,
                       column_names=workflow.get_column_names()))

    if request.method == 'POST' and form.is_valid():
        if not form.has_changed():
            return redirect('table:display')

        # Create the query to update the row
        column_names = [col.name for col in workflow.columns.all()]
        row_values = [
            form.cleaned_data[(FIELD_PREFIX + '%s') % idx]
            for idx in range(len(column_names))
        ]

        try:
            with transaction.atomic():
                # Update the row in the db
                update_row(workflow.get_data_frame_table_name(),
                           column_names,
                           row_values,
                           filter_dict={update_key: update_val})
                # verify that the "key" property is maintained in all the
                # columns.
                check_key_columns(workflow)
        except Exception as exc:
            form.add_error(None, str(exc))
            return render(
                request, 'dataops/row_filter.html', {
                    'workflow': workflow,
                    'form': form,
                    'cancel_url': reverse('table:display')
                })

        # Recompute all the values of the conditions in each of the actions
        # TODO: Explore how to do this asynchronously (or lazy)
        map(lambda act: act.update_n_rows_selected(), workflow.actions.all())

        # Log the event
        Log.objects.register(
            request.user, Log.TABLEROW_UPDATE, workflow, {
                'id':
                workflow.id,
                'name':
                workflow.name,
                'new_values':
                list(zip(column_names, [str(rval) for rval in row_values]))
            })

        return redirect('table:display')

    return render(request, 'dataops/row_filter.html', {
        'workflow': workflow,
        'form': form,
        'cancel_url': reverse('table:display')
    })
Пример #6
0
def get_table_visualization_items(
    workflow: models.Workflow,
    rowselect_key: Optional[str] = None,
    rowselect_val: Optional[Any] = None,
    pk: Optional[int] = None,
) -> Optional[Tuple[str, Dict]]:
    """Get a tuple with a template, and a dictionary to visualize a table.

    :param workflow: Workflow being processed
    :param rowselect_key: Optional key name to select a row
    :param rowselect_val: Optional value to select a row
    :param pk: Primary key of a view (could be none)
    :return:
    """
    # Get the data frame and the columns
    df_col_view = _get_df_and_columns(workflow, pk)
    if not df_col_view:
        return None
    df, columns_to_view, view = df_col_view

    if bool(rowselect_key):
        template = 'table/stat_row.html'
        row = sql.get_row(
            workflow.get_data_frame_table_name(),
            rowselect_key,
            rowselect_val,
            column_names=[col.name for col in columns_to_view],
        )
    else:
        row = None
        template = 'table/stat_view.html'

    vis_scripts = []
    visualizations = []
    context = {
        'style': 'max-width:{0}px; max-height:{1}px; margin: auto;'.format(
            VISUALIZATION_WIDTH,
            VISUALIZATION_HEIGHT),
    }
    for idx, column in enumerate(columns_to_view):

        # Add the title and surrounding container
        visualizations.append(
            '<hr/><h4 class="text-center">' + column.name + '</h4>')
        # If all values are empty, no need to proceed
        if all(not col_data for col_data in df[column.name]):
            visualizations.append(
                '<p>' + _('No values in this column') + '</p>')
            continue

        if row and not row[column.name]:
            visualizations.append(
                '<p class="alert-warning">' + _('No value in this column')
                + '</p>',
            )

        column_viz = _get_column_visualisations(
            column,
            df[[column.name]],
            vis_scripts=vis_scripts,
            viz_id='column_{0}'.format(idx),
            single_val=row[column.name] if row else None,
            context=context)

        visualizations.extend([vis.html_content for vis in column_viz])

    return template, {
        'value': rowselect_val,
        'view': view,
        'vis_scripts': vis_scripts,
        'visualizations': visualizations}