我在下面给出了代码...我想记录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_commit
与before_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()
这是更详细的终端日志
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
答案 0 :(得分:0)
由于Flask-SQLAlchemy中的错误,目前看来这些信号根本不起作用。带有修复程序的pull-request已经合并,可能会在Flask-SQLAlchemy的2.1版本中发布。