Проблемы с Sqlachemy. Не могу понять разницу - PullRequest
0 голосов
/ 08 ноября 2018

У меня есть следующий код

def update(project_id, code, description):

    if project_id is None:
        raise exception

    with session_handler() as session:
        project = session.query(Project).filter_by(project_id=project_id).first()
        project_upd = session.query(Project).filter_by(project_id=project_id)

    if project is None:
        raise ProjectDoesntExist(f"Project {project_id} does not exist.")
    data = _build_update_data(code, description)

    if  not data:
        raise ValueError("No code or description provided")

    project_upd.update(data)

Так что, если я заменю project_upd.update(data) на project.update(data), это выдаст следующую ошибку

Ошибка атрибута: объект проекта не имеет обновления атрибута.

Как я могу использовать только одну переменную?

1 Ответ

0 голосов
/ 08 ноября 2018

Хотя модель Project опущена, ясно, что у нее нет метода update() - что является нормой. Разница в том, что project привязан к объекту Project, а project_upd к Query объекту. Другими словами, первое представляет одну строку в таблице, сопоставленной с объектом, а второе представляет запрос к этой таблице.

Ваши варианты:

  1. Выполнить только инструкцию UPDATE и проверить, соответствует ли она каким-либо строкам, повысить, если нет.
  2. Извлечь строку / объект для обновления , проверить, существует ли он, и поднять, если нет, выполнить обновление.

Я предполагаю, что session_handler() фиксируется, если не возникло исключений. Если это не так, добавьте явное session.commit() при необходимости.

1. Один оператор UPDATE

def update(project_id, code, description):
    if project_id is None:
        raise exception

    data = _build_update_data(code, description)

    if not data:
        raise ValueError("No code or description provided")

    with session_handler() as session:
        row_count = session.query(Project).\
            filter_by(project_id=project_id).\
            update(data)

        if not row_count:
            raise ProjectDoesntExist(f"Project {project_id} does not exist.")

2. Выбрать и обновить

def update(project_id, code, description):
    if project_id is None:
        raise exception

    data = _build_update_data(code, description)

    if not data:
        raise ValueError("No code or description provided")

    with session_handler() as session:
        # Fetch FOR UPDATE so that no concurrent updates may proceed in between
        # getting the `Project` instance and actually updating it.
        project = session.query(Project).\
            filter_by(project_id=project_id).\
            with_for_update().\
            first()

        if project is None:
            raise ProjectDoesntExist(f"Project {project_id} does not exist.")

        for attr, val in data.items():
            setattr(project, attr, val)

Блокировка с помощью FOR UPDATE может быть немного ненужной в этом случае, так как новые значения, кажется, не зависят от предыдущего состояния объекта. Тем не менее, об этом нужно помнить.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...