sqlalchemy/flask:在初始插入后运行带有附加插入/更新提交的作业 // @event.listens_for(Request, "after_insert")

问题描述 投票:0回答:1

我有一个使用 Flask / sqlalchemy 的后端,它将记录插入到表中(“请求”)。 插入后,我想在后端运行额外的作业,从而应该对表进行额外的更新。

示例:假设我插入 3 条记录,并提交它们,“after_insert”将选取 3 个新创建的 id。我现在想通过特定的后端函数运行每个 id,这将进一步更新表(此处为函数“run_backend_job”)。

我目前遇到的问题是 sqlalchemy 不断抱怨如下,我无法弄清楚如何解决它。

我一直在考虑为第二次提交创建一个新会话,但无法让它工作(而且也不确定这是否是解决这个问题的正确方向)。

任何指示将不胜感激。

错误:

发生错误:此处无法调用方法‘commit()’;方法 '_prepare_impl()' 已经在进行中,这会导致 意外状态更改为 (此错误的背景位于:https://sqlalche.me/e/20/isce

代码:

from app import db
from sqlalchemy import event, func, inspect
# from flask_socketio import emit
from dataclasses import dataclass


@dataclass
class Request(db.Model):
    id: str = db.Column(db.Integer, primary_key=True)
    request_text: str = db.Column(db.String(400))  
    folder       : str = db.Column(db.String(400))       
    filename     : str = db.Column(db.String(400))          
    status       : str = db.Column(db.String(400))   
    added_from   : str = db.Column(db.String(400))  
    added_date   : str = db.Column(db.String(400))      
    updated_date : str = db.Column(db.String(400)) 

@event.listens_for(Request, "after_insert")
def emit_request_insert(mapper, connection, target):
    item_inserted = target.id
    # do some other stuff
    # emit('item_inserted', item_inserted, broadcast=True)
    # emit('counts_updated', broadcast=True)
    run_backend_job(target.id, target.request_text)


############  HANDLING OF JOBS ############

def current_time():
    return datetime.now(ZoneInfo('Europe/Zurich')).strftime("%m/%d/%Y, %H:%M:%S")

def run_backend_job(id, request_text):   
    time = current_time()
    try:  
        folder, filename = get_folder_filename(request_text)
        row = Request.query.filter_by(id=id).first()
        row.updated_date = current_time()
        row.folder = folder
        row.filename = filename   
        db.session.commit()
    except Exception as error:
        print("An error occurred:", error)
    return


def get_folder_filename(request_text):
    return ('/somepath/','somefilename.txt')
python-3.x sqlite flask sqlalchemy flask-sqlalchemy
1个回答
0
投票

普遍的共识是不惜一切代价避免事件监听器。它们非常脆弱,并且使业务逻辑难以遵循。例如,可以将其重构为用于创建请求的更简单的实用函数。下面是一些伪代码,可以给您一个想法。

def create_request(**kwargs):
    request = Request(**kwargs)
    folder, filename = get_folder_filename(request_text)
    request.updated_date = current_time()
    request.folder = folder
    request.filename = filename   
    db.session.add(request)

作为旁注,您可能希望使用日期列来表示日期。

© www.soinside.com 2019 - 2024. All rights reserved.