我将Flask示例Minitwit与MongoDB一起使用,它在Flask 0.9上工作正常,但升级到0.10.1后,当我尝试设置会话ID时,我在登录时收到错误。< / p>
似乎Flask 0.10.1中有changes与json有关。
代码段:
user = db.minitwit.user.find_one({'username': request.form['username']})
session['_id'] = user['_id']
我的github回购邮件中的完整代码。
基本上,我将Flask会话ID设置为来自MongoDB的用户的_id。
我尝试了这个SO question的前两个解决方案但没有成功。
好吧,做session ['_ id'] = str(user ['_ id'])摆脱错误信息,我已正确地重定向到时间线页面,但我实际上并没有登录。
我该如何解决这个问题?
编辑:复制/粘贴追溯:http://pastebin.com/qa0AL1fk
谢谢。
答案 0 :(得分:12)
编辑:更容易修复。您甚至不需要进行任何JSON编码/解码。
只需将会话['_ id']保存为字符串:
user = db.minitwit.user.find_one({'username': request.form['username']})
session['_id'] = str(user['_id'])
然后你想用session ['_ id']做任何事情,你必须用ObjectId()包装它,所以它作为ObjectId对象传递给MongoDB。
if '_id' in session:
g.user = db.minitwit.user.find_one({'_id': session['_id']})
为:
if '_id' in session:
g.user = db.minitwit.user.find_one({'_id': ObjectId(session['_id'])})
您可以在github repo上看到修补程序的完整差异。
如果有人想知道为什么'TypeError:ObjectId('')不是JSON可序列化的'“问题”出现在Flask 0.10.1中,那是因为他们改变了会话的存储方式。它们现在存储为JSON,因为MongoDB中的'_id'对象不是标准JSON,它无法序列化会话令牌,从而产生TypeError。请在此处了解更改:http://flask.pocoo.org/docs/upgrading/#upgrading-to-010
答案 1 :(得分:10)
默认情况下,JSON仅支持序列化(编码/解码)一组有限的对象类型。你可以扩展python JSON的解码器/编码器来处理这种情况。
在编码包含ObjectID的对象方面,例如,当创建ObjectIds时,客户端将传递给某个等待服务器,尝试:
import json
from bson.objectid import ObjectId
class Encoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, ObjectId):
return str(obj)
else:
return obj
然后,在您的代码中,在推送数据客户端之前 - &gt;服务器,运行:
json.dumps(obj, cls=Encoder)
服务器端,如果我们知道我们正在处理mongo docs(带有'_id'键的字典对象),我们可以定义一个json解码器钩子,如下所示:
def decoder(dct):
for k, v in dct.items():
if '_id' in dct:
try:
dct['_id'] = ObjectId(dct['_id'])
except:
pass
return dct
并使用如下调用来调用它:
doc = json.loads(in_doc, object_hook=decoder)
您可能需要对此代码进行一些调整,但是对于传递
的简单情况答案 2 :(得分:0)
这就是我最近修正错误的方法
{{1}}
答案 3 :(得分:0)
toString
将其转换为字符串,并且可以存储到会话中:
session['_id'] = user['_id'].toString()
替代
session['_id'] = str(user['_id'])
以上修正了我的错误。