如何在flask-sqlalchemy中更新另一个表后,在一个表中插入一个新对象

时间:2014-06-24 10:48:07

标签: python flask flask-sqlalchemy

我在我的项目中使用Flask-Sqlalchemy orm。

每当另一个表上有更新时,我必须在一个表中插入一个新对象。所以,我选择了models_committed signal.But,没有插入该对象。

@models_committed.connect_via(app)
def on_models_committed(sender, changes):
    print "signal",changes
    for obj, change in changes:
        if obj.__table__.strip() == 'task':
            print "works"
            obj = TaskHistory(task_id=target.id, task_status_id=target.task_status_id,  reason=target.reason)
            print "History Object",obj
            db.session.add(obj)
            db.session.commit()

回溯:

简短版本:

**sqlalchemy.exc.InvalidRequestError
InvalidRequestError: This session is in 'committed' state; no further SQL can be emitted within this transaction.**

长版:

Traceback (most recent call last):
  File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1836, in __call__
    return self.wsgi_app(environ, start_response)
  File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1820, in wsgi_app
    response = self.make_response(self.handle_exception(e))
  File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1403, in handle_exception
    reraise(exc_type, exc_value, tb)
  File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1817, in wsgi_app
    response = self.full_dispatch_request()
  File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1477, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1381, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1475, in full_dispatch_request
    rv = self.dispatch_request()
  File "/usr/local/lib/python2.7/dist-packages/flask_debugtoolbar/__init__.py", line 125, in dispatch_request
    return view_func(**req.view_args)
  File "/usr/lib/python2.7/cProfile.py", line 149, in runcall
    return func(*args, **kw)
  File "/usr/local/lib/python2.7/dist-packages/flask_superadmin/base.py", line 37, in inner
    return f(self, *args, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/flask_superadmin/base.py", line 37, in inner
    return f(self, *args, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/flask_superadmin/base.py", line 37, in inner
    return f(self, *args, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/flask_superadmin/base.py", line 37, in inner
    return f(self, *args, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/flask_superadmin/model/base.py", line 345, in edit
    pk=self.get_pk(instance), instance=instance)
  File "/usr/local/lib/python2.7/dist-packages/flask_superadmin/base.py", line 169, in render
    return render_template(template, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/flask/templating.py", line 128, in render_template
    context, ctx.app)
  File "/usr/local/lib/python2.7/dist-packages/flask/templating.py", line 110, in _render
    rv = template.render(context)
  File "/usr/share/pyshared/jinja2/environment.py", line 969, in render
    return self.environment.handle_exception(exc_info, True)
  File "/usr/share/pyshared/jinja2/environment.py", line 742, in handle_exception
    reraise(exc_type, exc_value, tb)
  File "/usr/local/lib/python2.7/dist-packages/flask_superadmin/templates/admin/model/edit.html", line 3, in top-level template code
    {% set name = admin_view.get_display_name() %}
  File "/usr/local/lib/python2.7/dist-packages/flask_superadmin/templates/admin/layout.html", line 21, in top-level template code
    {% block page_body %}
  File "/usr/local/lib/python2.7/dist-packages/flask_superadmin/templates/admin/layout.html", line 70, in block "page_body"
    {% block body %}{% endblock %}
  File "/usr/local/lib/python2.7/dist-packages/flask_superadmin/templates/admin/model/edit.html", line 26, in block "body"
    {{ lib.render_form(form, extra(), admin_view.can_edit, admin_view.can_delete) }}
  File "/usr/local/lib/python2.7/dist-packages/flask_superadmin/templates/admin/_macros.html", line 192, in template
    {{ render_formfield(form) }}
  File "/usr/local/lib/python2.7/dist-packages/flask_superadmin/templates/admin/_macros.html", line 180, in template
    {{ render_ff(form._fields[field_name]) }}
  File "/usr/local/lib/python2.7/dist-packages/flask_superadmin/templates/admin/_macros.html", line 142, in template
    {{ ff(class=class) }}
  File "/usr/local/lib/python2.7/dist-packages/wtforms/fields/core.py", line 139, in __call__
    return self.widget(self, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/flask_superadmin/form.py", line 96, in __call__
    return super(ChosenSelectWidget, self).__call__(field, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/wtforms/widgets/core.py", line 243, in __call__
    for val, label, selected in field.iter_choices():
  File "/usr/local/lib/python2.7/dist-packages/wtforms/ext/sqlalchemy/fields.py", line 108, in iter_choices
    for pk, obj in self._get_object_list():
  File "/usr/local/lib/python2.7/dist-packages/wtforms/ext/sqlalchemy/fields.py", line 101, in _get_object_list
    self._object_list = list((text_type(get_pk(obj)), obj) for obj in query)
  File "/usr/local/lib/python2.7/dist-packages/sqlalchemy/orm/query.py", line 2404, in __iter__
    return self._execute_and_instances(context)
  File "/usr/local/lib/python2.7/dist-packages/sqlalchemy/orm/query.py", line 2417, in _execute_and_instances
    close_with_result=True)
  File "/usr/local/lib/python2.7/dist-packages/sqlalchemy/orm/query.py", line 2408, in _connection_from_session
    **kw)
  File "/usr/local/lib/python2.7/dist-packages/sqlalchemy/orm/session.py", line 843, in connection
    close_with_result=close_with_result)
  File "/usr/local/lib/python2.7/dist-packages/sqlalchemy/orm/session.py", line 847, in _connection_for_bind
    return self.transaction._connection_for_bind(engine)
  File "/usr/local/lib/python2.7/dist-packages/sqlalchemy/orm/session.py", line 298, in _connection_for_bind
    self._assert_active()
  File "/usr/local/lib/python2.7/dist-packages/sqlalchemy/orm/session.py", line 192, in _assert_active
    "This session is in 'committed' state; no further "
InvalidRequestError: This session is in 'committed' state; no further SQL can be emitted within this transaction.

你能协助我解决这个问题吗?

我正在使用的工具:Python 2.7,Flask,SqlAlchemy

2 个答案:

答案 0 :(得分:0)

@models_committed.connect_via(app)
def on_models_committed(sender, changes):
    db_name = app.config["DB_NAME"]
    db_user = app.config["DB_USER"]
    db_pwd = app.config["DB_PWD"]
    conn = psycopg2.connect("dbname='%s' user='%s' host='localhost' password='%s'" %(db_name, db_user, db_pwd))
    query = "INSERT INTO task_history(task_id, task_status_id, updated_on, updated_by, reason)" +\
        "VALUES (%s, %s, '%s', %s, '%s')"
    cur = conn.cursor()
    for obj, change in changes:
        if str(obj.__table__).strip() == 'task':
            cur.execute(query % (obj.id, obj.task_status_id, "now()", 2, "Thats it"))
            conn.commit()

我的解决方案(我已回答了我的问题):

  1. 使用psycopg2
  2. 创建了单独的连接
  3. 插入新对象

答案 1 :(得分:0)

这不是解决方案,你只是解决了这个问题。你应该看看为什么你在for循环中重新分配了obj。删除重新分配可能会解决您的问题。