Flask sqlalchemy记录表中的所有更改都不起作用

时间:2014-11-13 11:01:16

标签: python sqlalchemy flask-sqlalchemy

我在下面给出了代码...我想记录User表中完成的所有更改(提交前+提交之后),并将它们存储为User2表中的JSON格式。将它们存储在JSON中工作正常;

但是flask-sqlalchemy的{​​{1}}不起作用。我以为我会在before_models_committed函数更改前和before_change函数更改后记录;

我在after_change函数中获得obj.as_dict()但在after_commit中没有

在文档https://pythonhosted.org/Flask-SQLAlchemy/signals.html中,他们说before_commitbefore_models_committed完全相同


任何更好的方法来做到这一点???? 或者如何解决以下问题????

models_committed

仅录制“after_commit”更改;我写下面的代码,但在这里我必须创建另一个会话;在这里;我无法获得from sqlalchemy.types import TypeDecorator, VARCHAR from sqlalchemy.ext.mutable import Mutable import json from bson import json_util class JSONEncodedDict(TypeDecorator): impl = VARCHAR def process_bind_param(self, value, dialect): if value is not None: value = json.dumps(value, default=json_util.default) return value def process_result_value(self, value, dialect): if value is not None: value = json.loads(value, object_hook=json_util.object_hook) return value class MutableDict(Mutable, dict): @classmethod def coerce(cls, key, value): if not isinstance(value, MutableDict): if isinstance(value, dict): return MutableDict(value) return Mutable.coerce(key, value) else: return value def __setitem__(self, key, value): dict.__setitem__(self, key, value) self.changed() def __delitem__(self, key): dict.__delitem__(self, key) self.changed() JsonType = MutableDict.as_mutable(JSONEncodedDict) from flask import Flask, request, Response, jsonify, g from flask_sqlalchemy import SQLAlchemy, models_committed, connection_stack, before_models_committed from flask_login import current_user from datetime import datetime from time import sleep import csv, json app = Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///flask_test.sqlite' # app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///:memory:' db = SQLAlchemy(app) class User(db.Model): id = db.Column(db.Integer, primary_key=True) username = db.Column(db.String(80), unique=True) email = db.Column(db.String(120), unique=True) pub_date = db.Column(db.DateTime) def __init__(self, username, email): self.username = username self.email = email self.pub_date = datetime.utcnow() def __repr__(self): return '<User %r>' % self.username def as_dict(self): return {c.name: getattr(self, c.name) for c in self.__table__.columns} class User2(db.Model): id = db.Column(db.Integer, primary_key=True) username = db.Column(db.String(80)) olddata = db.Column(JsonType) newdata = db.Column(JsonType) updatedtime = db.Column(db.DateTime) event = db.Column(db.String(30)) def __init__(self, username, olddata, newdata, event): self.username = username self.olddata = olddata self.newdata = newdata self.event = event self.updatedtime = datetime.utcnow() def __repr__(self): return '<User %r has commited some change>' % self.username def as_dict(self): return {c.name: getattr(self, c.name) for c in self.__table__.columns} @app.route("/change") def change_test(): username, email = request.args.get("username"), request.args.get("email") admin1 = User.query.filter_by(username=username).first() if username and email: if admin1: admin1.email = email db.session.commit() return Response(json.dumps({"username": username, "email": email, "update": True}), mimetype='application/json') else: admin = User(username, email) db.session.add(admin) db.session.commit() return Response(json.dumps({"username": username, "email": email, "insert": True}), mimetype='application/json') else: return Response(json.dumps({"error": "please enter username and email"}), mimetype='application/json') @before_models_committed.connect_via(app) def before_change(sender, changes): print "Before Change:::" print "Sender", sender print "changes: " for obj, change in changes: print "\t", obj, change print "Details: " print "\t", obj.as_dict() from sqlalchemy.orm.attributes import get_history @models_committed.connect_via(app) def after_change(sender, changes): print "After Change:::" print "Sender", sender print "changes: " # s2 = db.create_scoped_session({'scopefunc': connection_stack.__ident_func__}) for obj, change in changes: # for x in obj.__table__.columns: # history=get_history(changes, x) print "\t", obj, change print "Details: " print "\t", obj.as_dict() # admin1 = User.query.filter_by(username='admin').first() # print "Before change2::", admin1.as_dict() db.create_all() if __name__ == "__main__": app.run(debug=True, threaded=True) 值!!!

before_commit

和终端日志是:

@models_committed.connect_via(app)
def on_models_committed(sender, changes):
    s2 = db.create_scoped_session({'scopefunc': connection_stack.__ident_func__})
    for obj, change in changes:
        if change == "update" or change == "delete":
            curr_user = current_user
            if not curr_user:
                curr_user = "anonymous"

            user2 = User2(curr_user, obj.as_dict(), change)
            s2.add(user2)
            s2.commit()
    s2.close()

更新1:

这是更详细的终端日志

After Change:::
Sender <Flask 'app'>
changes: 
    <User u'testname'> insert
Details: 
    {'username': u'testname', 'pub_date': datetime.datetime(2014, 11, 13, 11, 24, 32, 592000), 'id': 2, 'email': u'testname@gmail.com'}
127.0.0.1 - - [13/Nov/2014 16:54:32] "GET /change?username=testname&email=testname@gmail.com HTTP/1.1" 200 -

* Running on http://127.0.0.1:5000/ * Restarting with reloader After Change::: Sender <Flask 'app'> changes: <User u'testname'> insert Details: {'username': u'testname', 'pub_date': datetime.datetime(2015, 1, 9, 5, 8, 2, 433000), 'id': 1, 'email': u'testname1@gmail.com'} 127.0.0.1 - - [09/Jan/2015 10:38:02] "GET /change?username=testname&email=testname1@gmail.com HTTP/1.1" 200 - 127.0.0.1 - - [09/Jan/2015 10:38:02] "GET /favicon.ico HTTP/1.1" 404 - After Change::: Sender <Flask 'app'> changes: <User u'testname1'> insert Details: {'username': u'testname1', 'pub_date': datetime.datetime(2015, 1, 9, 5, 8, 19, 9000), 'id': 2, 'email': u'testname11@gmail.com'} 127.0.0.1 - - [09/Jan/2015 10:38:19] "GET /change?username=testname1&email=testname11@gmail.com HTTP/1.1" 200 - After Change::: Sender <Flask 'app'> changes: <User u'testname'> update Details: {'username': u'testname', 'pub_date': datetime.datetime(2015, 1, 9, 5, 8, 2, 433000), 'id': 1, 'email': u'testname2@gmail.com'} 127.0.0.1 - - [09/Jan/2015 10:38:31] "GET /change?username=testname&email=testname2@gmail.com HTTP/1.1" 200 - 的输出如下:

pip freeze

1 个答案:

答案 0 :(得分:0)

由于Flask-SQLAlchemy中的错误,目前看来这些信号根本不起作用。带有修复程序的pull-request已经合并,可能会在Flask-SQLAlchemy的2.1版本中发布。