我试图在Flask应用程序中为用户会话实例化一个基本的Model实例。我要求我的类是JSON可序列化的,这让我措手不及。我认为会话字典只是一个存储会话信息的任意构造,但听起来有更多关于其使用的约束,其中一个显然是值是JSON可序列化的。还有哪些其他约束,这个JSON约束的目的是什么? Web应用程序是否期望通过JSON持久保存用户会话?这个要求来自哪里?受到启发?
@app.route( '/' , methods=['GET', 'POST'] )
def index():
"""index takes user to the home page of the application.
"""
# Create model instance for this user session
if 'model' not in session :
session['model'] = Model( )
File "C:\Anaconda3\lib\site-packages\flask\json.py", line 83, in default
return _json.JSONEncoder.default(self, o)
File "C:\Anaconda3\lib\json\encoder.py", line 173, in default
raise TypeError(repr(o) + " is not JSON serializable")
TypeError: <Model.Model object at 0x000000000770B6D8> is not JSON serializable
只是为了获得额外的背景,看起来会话对象是一个LocalProxy实例,它可能会提到事物的设计。
>>> type( session )
<class 'werkzeug.local.LocalProxy'>
答案 0 :(得分:1)
好的,所以在Miguel Grinberg的Flask Workshop在Pycon 2015上有一些很好的评论。对JSON支持的需求与这个会话数据的持久性有关,就像客户端上的cookie一样。因此,数据必须序列化以弥合服务器和客户端之间的差距。据他说......
所以flask支持这个会话对象,...在任何路由函数内 当您处理请求时,您将会话称为字典。 你写的任何东西都会被记住,下次你可以找到它 它将在那里,它将是用户特定的。
如果你有兴趣知道它是如何工作的,这就是Flask的内部, 你写给这本词典的任何东西,Flask都会放入一个cookie 它会将其发送给客户。所以这将存储在客户端 网页浏览器。这将是一个密码签名的cookie 确保用户不会篡改它,没有 攻击可能。你可以看到cookie里有什么,但你不能 修改它。默认情况下,Flask将数据本身写入cookie和 那个cookie送到客户端。还有很多其他框架可以做什么 默认是不同的。基本上他们做的是他们写入数据 服务器中的文件或数据库,然后他们写一个cookie 标识该数据的id,然后它们在中发送id 曲奇饼。所以Flask默认会在cookie中发送整个数据 没有必要在服务器中存储任何东西。
所以在我的特殊情况下,为了解决这个问题,我必须实现一个JSONEncoder,然后在将它转移到我的会话之前对其进行编码
<<Model.py>>
class ModelEncoder( JSONEncoder ) :
def default( self , obj ) :
if isinstance( obj , Model ):
return obj.to_json()
# Let the base class default method raise the TypeError
return json.JSONEncoder.default( self , obj )
class Model( JSONEncoder ) :
....
def to_json( self ) :
"""
to_json transforms the Model instance into a JSON string
"""
return jsonpickle.encode( self )
<<FlaskApp.py>>
...
# Create model instance for this user session
if 'model' not in session :
session['model'] = ModelEncoder().encode( Model( ) )