在 FLASK 和 python 中使用 mongo
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19877903/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Using mongo with FLASK and python
提问by Richard
I am trying to learn python, mongodb and flask and am using the VERY EXCELLENT blog from Miguel Grinberg who provides a great set of tutorials at blog.miguelgrinberg.com
我正在尝试学习 python、mongodb 和flask,并且正在使用 Miguel Grinberg 的非常优秀的博客,他在 blog.miguelgrinberg.com 上提供了一套很棒的教程
I got a small RESTful server working fine but now want to pull stuff from mongo not mysql
我有一个小型 RESTful 服务器工作正常,但现在想从 mongo 而不是 mysql 中提取东西
I can pull a mongo record out using the code below but am struggling to get it to render.
我可以使用下面的代码提取 mongo 记录,但正在努力让它呈现。
I have used arrows in the code below to show where I am struggling, lack of experience I think. Any thoughts would be appreciated.
我在下面的代码中使用了箭头来显示我在哪里挣扎,我认为缺乏经验。任何想法将不胜感激。
#!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)
Any help appreciated, page[0] is the code that's just not working I get a
感谢任何帮助,页面 [0] 是无法正常工作的代码,我得到了
TypeError: ObjectId('527e17c538320915e9893f17') is not JSON serializable
TypeError: ObjectId('527e17c538320915e9893f17') 不是 JSON 可序列化的
Thanks in advance
提前致谢
BTW Can't recommend Miguel's mega tutorial enough as a place to start to build stuff
顺便说一句,不能推荐 Miguel 的大型教程足以作为开始构建东西的地方
采纳答案by zero323
First of all find_one
will return single dictionary or None if there is no matching element in collection. So I think that page[0]
is equivalent to getting value of page dictionary for key 0
find_one
如果集合中没有匹配的元素,首先将返回单个字典或 None 。所以我认为这page[0]
相当于获取页面字典的键值0
If returned documents contains ObjectId
as _id
you cannot simply use jsonify
because, like ObjectId
is not JSON serializable.
You can use something like this:
如果返回的文档包含ObjectId
as_id
您不能简单地使用,jsonify
因为,likeObjectId
不是 JSON 可序列化的。你可以使用这样的东西:
jsonify({ 'page': make_public_page({k:v for k, v in page.items() if k != '_id'}))
or you can simply remove _id
by calling page.pop('_id')
或者你可以简单地_id
通过调用删除page.pop('_id')
You can also use bson.json_util
. It contains tools for conversion between BSON and JSON.
您也可以使用bson.json_util
. 它包含用于在 BSON 和 JSON 之间转换的工具。
from flask import Response
from bson import json_util
And then replace jsonify
with something similar to this:
然后jsonify
用类似的东西替换:
return Response(
json_util.dumps({'page' : make_public_page(page)}),
mimetype='application/json'
)
Edit
编辑
If you want short and dirty way of dealing with the problem you can do it like this:
如果您想要处理问题的简短而肮脏的方式,您可以这样做:
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))
回答by Miguel
From what I see in your code it appears you are not using Mongo's own IDs (which are stored in key _id
), but instead you are generating your own integer IDs, which you store in key id
. Is this correct?
从我在您的代码中看到的内容来看,您似乎没有使用 Mongo 自己的 ID(存储在 key 中_id
),而是生成自己的整数 ID,并将其存储在 key 中id
。这样对吗?
The problem with your code is that the Mongo _id
key is in the dict
objects that you send to make_public_page()
, and those cannot be serialized to JSON.
您的代码的问题在于 Mongo_id
密钥位于dict
您发送到的对象中make_public_page()
,而这些对象无法序列化为 JSON。
You can address this problem by skipping key _id
:
您可以通过跳过 key 来解决此问题_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
As a side note, I think it is better to not invent your own IDs and just use the ones from Mongo.
作为旁注,我认为最好不要发明自己的 ID,而只使用 Mongo 的 ID。
回答by enthus1ast
you could set the default encoder:
您可以设置默认编码器:
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 )
or you could subclass json.encoder.JSONEncoder
或者你可以继承 json.encoder.JSONEncoder