나는 아래 주어진 코드를 작성했습니다 ... 나는 (변경 전 커밋 + 커밋 후) User
테이블에서 수행 된 모든 변경 내용을 기록하고이를 User2
테이블에 JSON 형식으로 저장하려고합니다. . JSON에 저장하면 잘 작동합니다.
이지만 flask-sqlalchemy
의 before_models_committed
이 작동하지 않습니다. 나는 변화 전의 before_change
기능과 변경 후 기록 할 것이라고 생각했다 after_change
기능;
내가 after_commit
기능에 obj.as_dict()
를 얻을 수 있지만, 문서 https://pythonhosted.org/Flask-SQLAlchemy/signals.html에서 before_commit
에 그들은 before_models_committed
작품 정확히 같은 더 좋은 방법 models_committed
으로이 작업을 수행 할 수 있다는 말을하지 ???? 또는 아래 문제를 해결하는 방법 ????플라스크 sqlalchemy 레코드 테이블의 모든 변경 내용이 작동하지 않습니다
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)
"after_commit"변경 사항 만 기록됩니다. 나는 코드 아래에 썼다. 그러나 여기 나는 다른 세션을 만들어야한다. 그리고 여기도. 나는 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'[email protected]'}
127.0.0.1 - - [13/Nov/2014 16:54:32] "GET /change?username=testname&[email protected] HTTP/1.1" 200 -
업데이트 1 : 여기
보다 상세한 단말 로그
* 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'[email protected]'}
127.0.0.1 - - [09/Jan/2015 10:38:02] "GET /change?username=testname&[email protected] 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'[email protected]'}
127.0.0.1 - - [09/Jan/2015 10:38:19] "GET /change?username=testname1&[email protected] 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'[email protected]'}
127.0.0.1 - - [09/Jan/2015 10:38:31] "GET /change?username=testname&[email protected] HTTP/1.1" 200 -
및 pip freeze
의 출력은 그대로 아래 :
alembic==0.6.7
backports.ssl-match-hostname==3.4.0.2
blinker==1.3
certifi==14.05.14
cffi==0.8.6
click==3.3
colorama==0.3.2
cryptography==0.6.1
decorator==3.4.0
diesel==3.0.5
dulwich==0.9.9
email==4.0.2
Flask==0.10.1
Flask-Bcrypt==0.6.0
Flask-Bootstrap==3.2.0.2
Flask-Bootstrap3==3.1.1.3
flask-cache==0.13
Flask-Login==0.2.11
Flask-Migrate==1.2.0
flask-mongoengine==0.7.1
Flask-Script==2.0.5
Flask-Session==0.1.1
Flask-SQLAlchemy==2.0
Flask-SQLAlchemySession==0.0.1
Flask-Storage==0.1.0
Flask-Uploads==0.1.3
Flask-WTF==0.10.2
freeze==0.8.0
GitPython==0.1.7
greenlet==0.4.5
ipython==2.3.1
itsdangerous==0.24
jdcal==1.0
Jinja2==2.7.3
jsonpickle==0.8.0
Mako==1.0.0
MarkupSafe==0.23
matplotlib==1.4.2
mongoengine==0.8.7
mysql-connector-python==1.0.12
networkx==1.9.1
nltk==3.0.0
numpy==1.8.1
openpyxl==1.8.6
pbr==0.10.0
psutil==2.1.3
PuLP==1.5.6
py==1.4.25
pycosat==0.6.0
pycparser==2.10
pymongo==2.7.2
PyMySQL==0.6.2
pyOpenSSL==0.14
pyparsing==1.5.7
pyreadline==2.0
pysoundcard==0.5.0
pytest==2.6.3
python-dateutil==2.3
pytz==2014.10
pywin32==219
PyYAML==3.11
pyzmq==14.4.1
requests==2.4.3
schedule==0.3.1
scikit-learn==0.15.2
scipy==0.13.3
simplejson==3.6.5
six==1.8.0
SQLAlchemy==0.9.8
sqlalchemy-migrate==0.9.2
sqlparse==0.1.13
Tempita==0.5.2
tornado==4.0.2
trie==0.1.1
Twiggy==0.4.5
Twisted==14.0.2
uuid==1.30
validator==2.0.6
validator.py==1.2.0
validators==0.7
virtualenv==1.9.1
webapp2==2.5.2
Werkzeug==0.9.6
wheel==0.24.0
Whoosh==2.6.0
wrapt==1.9.0
WTForms==2.0.1
xlrd==0.9.3
xmldict==0.4.1
zope.interface==4.1.1
'''pip freeze'''의 출력으로 답을 편집하여 실행중인 모든 버전을 볼 수 있습니다. – opyate
@opyate : 나는'pip freeze'의 출력으로 게시물을 업데이트했고, 실행중인 앱의 자세한 터미널 로그를 추가했습니다. – namit