将 mongo 与 FLASK 和 python 一起使用
Posted
技术标签:
【中文标题】将 mongo 与 FLASK 和 python 一起使用【英文标题】:Using mongo with FLASK and python 【发布时间】:2013-11-21 13:48:33 【问题描述】:我正在尝试学习 python、mongodb 和烧瓶,并且正在使用 Miguel Grinberg 的非常优秀的博客,他在 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 = ":mysecretpassword@"
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)
感谢任何帮助,page[0] 是无法正常工作的代码,我得到了
TypeError: ObjectId('527e17c538320915e9893f17') 不是 JSON 可序列化的
提前致谢
顺便说一句,不能推荐 Miguel 的大型教程作为开始构建东西的地方
【问题讨论】:
这有点晚了,但你可以看看github.com/Bleezworld/flask_skeleton,它是一个mongodb/Flask 网站骨架,有一些使用示例(用户登录等) 【参考方案1】:您可以设置默认编码器:
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
【讨论】:
【参考方案2】:首先find_one
将返回单个字典或 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')
来删除_id
您也可以使用bson.json_util
。它包含用于在 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))
【讨论】:
感谢 sero - 使用您的 page.pop('_id') 看起来与 Miguels 解释结合使用会有所帮助。感谢您抽出宝贵时间回复。我没有足够的代表来推广这个答案,但当我这样做时会这样做 我已经发布了一个用替代方法处理问题的编辑。它不是很优雅但很有效。【参考方案3】:根据我在您的代码中看到的内容,您似乎没有使用 Mongo 自己的 ID(存储在密钥 _id
中),而是生成了自己的整数 ID,并将其存储在密钥 id
中。这是正确的吗?
您的代码的问题在于 Mongo _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,而只使用 Mongo 的 ID。
【讨论】:
是的,你是对的,我带着我自己的 ID,对 mongo 和 nosql 非常陌生,所以仍然处于学习曲线的陡峭部分。关于使用本机 _id 的好建议,永远不会知道它无法转换 mongo 值。非常感谢,我明天继续。以上是关于将 mongo 与 FLASK 和 python 一起使用的主要内容,如果未能解决你的问题,请参考以下文章
Python / Flask - 将 flask_restless 与 flask_httpauth 一起使用