Utilisation de mongo avec flacon et python
j'essaie d'apprendre python, mongodb et flask et j'utilise le Très EXCELLENT blog de Miguel Grinberg qui fournit un grand ensemble de tutoriels à blog.miguelgrinberg.com
j'ai un petit serveur de repos qui fonctionne bien, mais maintenant je veux tirer des trucs de mongo pas mysql
je peux extraire un enregistrement de mongo en utilisant le code ci-dessous mais j'ai du mal à le rendre.
j'ai utilisé des flèches dans le code ci-dessous pour afficher là où je me bats, le manque d'expérience je pense. Toute pensée serait appréciée.
#!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)
toute aide appréciée, page[0] est le code qui ne fonctionne pas je reçois un
TypeError: ObjectId ('527e17c538320915e9893f17') is not JSON serializable
Merci d'avance
BTW ne peut pas recommander le tutoriel mega De Miguel assez comme un endroit pour commencer à construire des choses
3 réponses
tout d'Abord find_one
sera de retour seul dictionnaire ou Aucun si il n'y a pas d'élément correspondant dans la collection. Donc je pense que page[0]
est équivalent à obtenir la valeur du dictionnaire de la page pour la clé 0
si les documents retournés contiennent ObjectId
comme _id
vous ne pouvez pas simplement utiliser jsonify
parce que, comme ObjectId
n'est pas sérialisable JSON.
Vous pouvez utiliser quelque chose comme ceci:
jsonify({ 'page': make_public_page({k:v for k, v in page.items() if k != '_id'}))
ou vous pouvez il suffit de supprimer _id
en appelant page.pop('_id')
vous pouvez également utiliser bson.json_util
. Il contient des outils pour la conversion entre BSON et JSON.
from flask import Response
from bson import json_util
et remplacer jsonify
par quelque chose de similaire:
return Response(
json_util.dumps({'page' : make_public_page(page)}),
mimetype='application/json'
)
Modifier
Si vous voulez court et sale manière de traiter le problème, vous pouvez le faire comme ceci:
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))
vous pouvez définir l'encodeur par défaut:
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 )
ou vous pourriez classer json.encodeur.JSONEncoder
D'après ce que je vois dans votre code, il semble que vous n'utilisez pas les propres IDs de Mongo (qui sont stockés dans la clé _id
), mais au lieu de cela vous générez vos propres IDs entiers, que vous stockez dans la clé id
. Est-ce correct?
le problème avec votre code est que la clé Mongo _id
est dans les objets dict
que vous envoyez à make_public_page()
, et ceux-ci ne peuvent pas être sérialisés à JSON.
, Vous pouvez résoudre ce problème en touche de saut _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
comme note secondaire, je pense qu'il est préférable de ne pas inventer vos propres ID et juste utiliser ceux de Mongo.