2013-07-13 23 views
10

Tôi chia nhỏ ví dụ Flask, Minitwit, để làm việc với MongoDB và nó hoạt động tốt trên Flask 0.9, nhưng sau khi nâng cấp lên 0.10. 1 Tôi nhận được lỗi trong tiêu đề khi tôi đăng nhập khi tôi cố gắng thiết lập id phiên.Lấy 'TypeError: ObjectId (' ') không phải là JSON serializable' khi sử dụng Flask 0.10.1

Dường như có changes trong Flask 0.10.1 liên quan đến json.

Đoạn mã:

user = db.minitwit.user.find_one({'username': request.form['username']}) 
session['_id'] = user['_id'] 

Toàn mã trong github repo của tôi.

Về cơ bản, tôi đặt Id phiên Flask thành _id của người dùng từ MongoDB.

Tôi đã thử hai giải pháp đầu tiên từ SO question này mà không thành công.

Vâng, làm phiên str [ '_ id'] = (user [ '_ id']) giúp loại bỏ các thông báo lỗi và tôi đang chuyển hướng đúng cách để trang timeline nhưng tôi không thực sự đăng nhập.

Làm cách nào để khắc phục sự cố này?

EDIT: Sao chép/dán các traceback: http://pastebin.com/qa0AL1fk

Cảm ơn bạn.

Trả lời

12

EDIT: Ngay cả dễ dàng hơn sửa chữa. Bạn thậm chí không cần phải làm bất kỳ mã hóa/giải mã JSON nào.

Chỉ cần lưu phiên [ '_ id'] như là một chuỗi:

user = db.minitwit.user.find_one({'username': request.form['username']}) 
session['_id'] = str(user['_id']) 

Và sau đó ở khắp mọi nơi bạn muốn làm điều gì đó với bạn phải quấn nó với ObjectId (phiên [ '_ id']) để nó được truyền như một đối tượng ObjectId đến MongoDB.

if '_id' in session: 
    g.user = db.minitwit.user.find_one({'_id': session['_id']}) 

tới:

if '_id' in session: 
    g.user = db.minitwit.user.find_one({'_id': ObjectId(session['_id'])}) 

Bạn có thể xem diff đầy đủ cho việc sửa chữa trên github repo tôi.

Nếu có ai quan tâm để biết tại sao vấn đề 'TypeError: ObjectId (' ') không phải là JSON serializable' "xuất hiện trong Flask 0.10.1, đó là vì chúng đã thay đổi cách phiên được lưu trữ. Bây giờ chúng được lưu trữ dưới dạng JSON vì vậy đối tượng '_id' trong MongoDB không phải là JSON tiêu chuẩn, nó không thể tuần tự hóa mã thông báo phiên, do đó cung cấp cho TypeError. Tìm hiểu về sự thay đổi ở đây: http://flask.pocoo.org/docs/upgrading/#upgrading-to-010

9

JSON chỉ hỗ trợ tuần tự hóa (mã hóa/giải mã) một tập hợp các loại đối tượng hạn chế theo mặc định. Bạn có thể mở rộng bộ giải mã/bộ mã hóa của python JSON để xử lý tình huống này.

Xét về mã hóa một đối tượng, trong đó có trên ObjectId, ví dụ, khi ObjectIds được tạo ra phía khách hàng, mà sẽ được thông qua cùng với một số máy chủ chờ, hãy thử:

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 

Sau đó, trong mã của bạn, trước khi đẩy dữ liệu khách hàng -> máy chủ, hãy chạy:

json.dumps(obj, cls=Encoder) 

Server side, nếu chúng ta biết chúng ta đang làm việc với tài liệu Mongo, (đối tượng từ điển với một '_id' key), chúng ta có thể xác định một cái móc json giải mã như sau:

def decoder(dct): 
    for k, v in dct.items(): 
     if '_id' in dct: 
      try: 
       dct['_id'] = ObjectId(dct['_id']) 
      except: 
       pass 
     return dct 

Và gọi nó bằng một cuộc gọi như sau:

doc = json.loads(in_doc, object_hook=decoder) 

Bạn có lẽ sẽ cần phải thích ứng với mã này một chút, nhưng đối với các trường hợp đơn giản của truyền

0

Đây là cách tôi vừa mới sửa lỗi

@app.route('/') 
def home(): 
    docs = [] 
    for doc in db.person.find(): 
     doc.pop('_id') 
     docs.append(doc) 
    return jsonify(docs) 
0

toString chuyển nó vào chuỗi và có thể lưu trữ tới phiên:

session['_id'] = user['_id'].toString() 

thay thế session['_id'] = str(user['_id'])

Lỗi trên đã sửa lỗi cho tôi.

Các vấn đề liên quan