2013-11-09 91 views
6

我努力學習Python,和mongodb的燒瓶中,用米格爾格林貝格非常優秀的博客誰在blog.miguelgrinberg.com使用蒙戈用燒瓶中,蟒蛇

我有一個小提供了極大的一系列教程,我RESTful服務器工作正常,但現在想從Mongo拉東西不是mysql

我可以使用下面的代碼拉出一個mongo記錄,但我努力讓它呈現。

我在下面的代碼中使用了箭頭來顯示我在掙扎的地方,我覺得缺乏經驗。任何想法將不勝感激。

#!flask/bin/python 
from flask import Flask, jsonify, abort, make_response, url_for 
from pymongo import MongoClient 

# connect to mongo database hosted on AWS 
# the script expects the host name to be in /etc/hosts file 

''' 
Set up global variables here 
''' 
mongo_server = "mongo_api" 
mongo_port = "27017" 
mongo_user = "admin" 
mongo_passwd = ":[email protected]" 
connect_string = "mongodb://"+ mongo_user 
          + mongo_passwd 
          + mongo_server 
          + ":" 
          + mongo_port 

app = Flask(__name__) 

@app.errorhandler(404) 
def not_found(error): 
    return make_response(jsonify({ 'error': 'Notfound' }), 404) 


def make_public_page(page): 
    new_page = {} 
    for field in page: 
     if field == 'id': 
      new_page['uri'] = url_for('get_page', page_id = page['id'], _external = True) 
     else: 
      new_page[field] = page[field] 
    return new_page 



@app.route('/api/v1.0/pages/<int:page_id>',methods = ['GET']) 
def get_page(page_id): 
    ''' 
    Can connect otherwise exit with message 
    ''' 
    try: 
     connection = MongoClient(connect_string) # equal to > show dbs 
    except: 
     exit("Error: Unable to connect to the database") # exit with an error 
    ''' 
    connect to database and pull back collections 
    ''' 
    db = connection.test_database # equal to > use test_database     
    pages = db.pages 
    page = pages.find_one({"id": int(page_id)}) <------ this pulls back a document 
    if page == None: <---- if a null set comes back then this works great 
     abort(404) 
    return jsonify({ 'page' : make_public_page(page[0])}) <- error says its not json 

if __name__ == '__main__': 
    app.run(debug = True) 

讚賞任何幫助,頁[0]是,只是沒有工作,我得到一個

類型錯誤代碼:物件( '527e17c538320915e9893f17')不是JSON序列化

在此先感謝

順便說一句,不能推薦米格爾的超級教程足以作爲一個地方開始構建的東西

+0

這是晚,但你可以看看https://github.com/Bleezworld/ flask_skeleton,它是一個mongodb/Flask網站框架,其中包含一些使用示例(用戶登錄等) – Thomas

回答

11

首先find_one將返回罪gle字典或None,如果集合中沒有匹配的元素。所以我認爲,page[0]相當於獲得頁字典的價值關鍵0

如果返回文件包含ObjectId_id你不能簡單地用jsonify因爲像ObjectId不是JSON序列化。 您可以使用這樣的事情:

jsonify({ 'page': make_public_page({k:v for k, v in page.items() if k != '_id'})) 

,或者你可以簡單地通過調用page.pop('_id')

您還可以使用bson.json_util刪除_id。它包含用於BSON和JSON之間轉換的工具。

from flask import Response 
from bson import json_util 

然後用類似這樣的東西取代jsonify

return Response(
    json_util.dumps({'page' : make_public_page(page)}), 
    mimetype='application/json' 
) 

編輯

如果你想對付你可以做這樣的問題的短期和骯髒的方式:

from bson import json_util, ObjectId 
import json 

#Lets create some dummy document to prove it will work 
page = {'foo': ObjectId(), 'bar': [ObjectId(), ObjectId()]} 

#Dump loaded BSON to valid JSON string and reload it as dict 
page_sanitized = json.loads(json_util.dumps(page)) 
+0

感謝sero -using您的page.pop('_ id')看起來會與Miguels的解釋結合起來。感謝您花時間回覆讚賞。我沒有足夠的代表來宣傳這個答案,但是當我做時 – Richard

+0

我已經發布了一個處理問題的替代方式的編輯。這不是非常優雅而有效的。 – zero323

1

Fro m我在代碼中看到的內容顯示您沒有使用Mongo自己的ID(存儲在密鑰_id中),而是生成自己的整數ID,存儲在密鑰id中。它是否正確?

與您的代碼的問題是,蒙戈_id關鍵是,你要發送的make_public_page()對象dict,而那些不能被序列化到JSON。

您可以通過跳過鍵_id解決這個問題:

def make_public_page(page): 
    new_page = {} 
    for field in page: 
     if field == 'id': 
      new_page['uri'] = url_for('get_page', page_id = page['id'], _external = True) 
     elif field != '_id': 
      new_page[field] = page[field] 
    return new_page 

作爲一個方面說明,我覺得這是更好地沒有發明自己的ID,並只使用那些從蒙戈。

+0

是的,你是對的,我帶着自己的ID,對於mongo和nosql來說非常新,所以仍然在學習曲線的陡峭部分。關於使用本機_id的好建議,並且永遠不會得到它無法轉換mongo值。非常感謝我明天將推動。 – Richard

2

,你可以設置默認編碼器:

import json 
from bson.objectid import ObjectId 

def newEncoder(o): 
    if type(o) == ObjectId: 
     return str(o) 
    return o.__str__ 

.... 

return json.dumps(list(somecollection.find(expr)) , default=newEncoder) 

,或者你可以繼承json.encoder.JSONEncoder