Хотя модель Project
опущена, ясно, что у нее нет метода update()
- что является нормой. Разница в том, что project
привязан к объекту Project
, а project_upd
к Query
объекту. Другими словами, первое представляет одну строку в таблице, сопоставленной с объектом, а второе представляет запрос к этой таблице.
Ваши варианты:
- Выполнить только инструкцию UPDATE и проверить, соответствует ли она каким-либо строкам, повысить, если нет.
- Извлечь строку / объект для обновления , проверить, существует ли он, и поднять, если нет, выполнить обновление.
Я предполагаю, что 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
может быть немного ненужной в этом случае, так как новые значения, кажется, не зависят от предыдущего состояния объекта. Тем не менее, об этом нужно помнить.