Example #1
0
async def create_or_update(row: Dict, model_id: Text) -> Tuple:
    try:
        model_data = cfg.models[model_id]
        row = prepare_request_params(row, model_id, model_data)
        obj = (await model_data["model"].create(**row)).to_dict()
        obj_id = get_obj_id_from_row(model_data, obj)
        return obj_id, None, None
    except asyncpg.exceptions.UniqueViolationError as e:
        if cfg.csv_update_existed:
            obj_id = prepare_request_params(
                get_obj_id_from_row(model_data, row), model_id, model_data)
            obj = await get_by_params(obj_id, model_data["model"])
            await obj.update(**row).apply()
            return None, obj_id, None
        else:
            return None, None, (row, e.args)
    except Exception as e:
        return None, None, (row, e.args)
Example #2
0
async def model_edit_post(request, model_id):
    model_data = cfg.models[model_id]
    model = model_data["model"]
    columns_data = model_data["columns_data"]
    previous_id: Dict = utils.extract_obj_id_from_query(
        dict(request.query_args)["_id"])
    previous_id: Dict = utils.correct_types(previous_id,
                                            columns_data,
                                            no_default=True)

    request_params = {
        key: request.form[key][0] if request.form[key][0] != "None" else None
        for key in request.form
    }
    request_params = utils.prepare_request_params(request_params, model_id,
                                                  model_data)
    try:
        if not model_data["identity"]:
            old_obj = previous_id
            await update_all_by_params(request_params, previous_id, model)
            obj = request_params
        else:
            obj = await get_by_params(previous_id, model)
            old_obj = obj.to_dict()
            await obj.update(**request_params).apply()
            obj = obj.to_dict()
        changes = utils.get_changes(old_obj, obj)
        new_obj_id = utils.get_obj_id_from_row(model_data, request_params,
                                               previous_id)
        message = f"Object with id {previous_id} was updated."
        if changes:
            message += f'Changes: from {changes["from"]} to {changes["to"]}'
        request.ctx.flash(message, "success")
        log_history_event(request, message, previous_id)
    except asyncpg.exceptions.ForeignKeyViolationError as e:
        request.ctx.flash(
            f"ForeignKey error. "
            f"Impossible to edit field for row {previous_id}, "
            f"because exists objects that depend on it. {e}",
            "error",
        )
    except asyncpg.exceptions.UniqueViolationError:
        request.ctx.flash(
            f"{model_id.capitalize()} with such id already exists", "error")
    except asyncpg.exceptions.NotNullViolationError as e:
        column = e.args[0].split("column")[1].split("violates")[0]
        request.ctx.flash(f"Field {column} cannot be null", "error")
    return await render_add_or_edit_form(request, model_id, new_obj_id)
Example #3
0
async def model_add(request, model_id):
    model_data = cfg.models[model_id]
    request_params = {key: request.form[key][0] for key in request.form}
    request_params = utils.prepare_request_params(request_params, model_id,
                                                  model_data)
    not_filled = [
        x for x in model_data["required_columns"] if x not in request_params
    ]
    if not_filled:
        request.ctx.flash(f"Fields {not_filled} required. Please fill it",
                          "error")
    else:
        try:
            obj = await model_data["model"].create(**request_params)
            obj_id = utils.get_obj_id_from_row(model_data, obj.to_dict())
            message = f"Object with {obj_id} was added."
            request.ctx.flash(message, "success")
            log_history_event(request, message, obj_id)
        except (
                asyncpg.exceptions.StringDataRightTruncationError,
                ValueError,
                asyncpg.exceptions.ForeignKeyViolationError,
        ) as e:
            request.ctx.flash(e.args, "error")
        except asyncpg.exceptions.UniqueViolationError:
            request.ctx.flash(
                f"{model_id.capitalize()} with such id already exists",
                "error")
        except asyncpg.exceptions.NotNullViolationError as e:
            column = e.args[0].split("column")[1].split("violates")[0]
            request.ctx.flash(f"Field {column} cannot be null", "error")
        except asyncpg.exceptions.UndefinedTableError:
            request.ctx.flash(
                f"Somebody stole the table. Table {model_id} does not exist",
                "error")

    return await render_add_or_edit_form(request, model_id)
Example #4
0
async def upload_composite_csv_row(row, header, tables_indexes, stack,
                                   unique_keys):
    # if composite header each column == {'table': {}, 'column': None}
    # todo: refactor this huge code
    table_num = 0
    previous_table_name = None
    id_added = []
    id_updated = []
    for table_name, indexes in tables_indexes.items():
        # {'start': None, 'end': None}
        table_header = deepcopy(header)[indexes["start"]:indexes["end"] +
                                        1  # noqa E203
                                        ]
        table_row_data = deepcopy(row)[indexes["start"]:indexes["end"] +
                                       1  # noqa E203
                                       ]
        if not any(table_row_data):
            if table_header[0]["table"][0] == table_header[0]["table"][1]:
                previous_table_name = table_name
            else:
                for elem in stack[::-1]:
                    if elem in table_header[0]["table"][1]:
                        previous_table_name = elem
                        break
            table_num += 1
            continue
        if table_header[0]["table"][0] == table_header[0]["table"][1]:
            model_id = table_name
            columns_data = cfg.models[model_id]["columns_data"]
        else:
            model_id = None
            columns_indexes_remove = []
            for index, field_value in enumerate(table_header):
                if isinstance(field_value["column"], CompositeType):
                    model_id = table_row_data[index]
                    table_row_data.pop(index)
                    break
            if model_id:
                table_header.pop(index)
            else:
                model_id = cfg.composite_csv_settings[table_name][
                    "pattern"].replace("*", previous_table_name)
            columns_data = cfg.models[model_id]["columns_data"]

            for index, value in enumerate(table_header):
                if value["column"] not in columns_data:
                    # column not in this table
                    columns_indexes_remove.append(index)
            for num, index in enumerate(columns_indexes_remove):
                table_header.pop(index - num)
                table_row_data.pop(index - num)

        table_row = {
            table_header[num]["column"]: value
            for num, value in enumerate(table_row_data)
        }
        model_data = cfg.models[model_id]
        try:
            table_row = prepare_request_params(table_row, model_id, model_data)
            if table_num > 0:
                column, target_column = cfg.models[model_id]["foreign_keys"][
                    previous_table_name]
                foreing_column_value = unique_keys[previous_table_name][
                    target_column]
                table_row[column] = foreing_column_value
            id_added, id_updated, error = await create_or_update(
                table_row, model_id)
            if id_added or id_updated:
                id_ = id_added if id_added else id_updated
                new_obj = (await get_by_params(id_,
                                               model_data["model"])).to_dict()

                if indexes["start"] == 0:
                    unique_keys = {}
                unique_keys[model_id] = new_obj
                stack.append(model_id)
                previous_table_name = model_id
                table_num += 1
            else:
                return None, id_updated, error, stack, unique_keys
        except Exception as e:
            return None, None, (table_row, e), stack, unique_keys
            # TODO: right now just abort if error during composite file upload
    return id_added, id_updated, None, stack, unique_keys
Example #5
0
async def upload_simple_csv_row(row, header, model_id):
    row = {header[index]: value for index, value in enumerate(row)}
    row = prepare_request_params(row, model_id, cfg.models[model_id])
    return await create_or_update(row, model_id)