Flask 扩展 Flask-PyMongo
安装
pip install Flask-PyMongo
初始化Pymongo实例
from flask import Flask from flask.ext.pymongo import PyMongo app = Flask(__name__) app.config.update( MONGO_HOST='localhost', MONGO_PORT=27017, MONGO_USERNAME='bjhee', MONGO_PASSWORD='111111', MONGO_DBNAME='flask' ) mongo = PyMongo(app)
在应用配置中,我们指定了MongoDB的服务器地址,端口,数据库名,用户名和密码。对于上面的配置,我们也可以简化为:
app.config.update( MONGO_URI='mongodb://localhost:27017/flask', MONGO_USERNAME='bjhee', MONGO_PASSWORD='111111' )
在同一应用中,我们还可以初始化两个以上的Flask-PyMongo实例,分别基于不同的配置项:
app.config.update( MONGO_URI='mongodb://localhost:27017/flask', MONGO_USERNAME='bjhee', MONGO_PASSWORD='111111', MONGO_TEST_URI='mongodb://localhost:27017/test' ) mongo = PyMongo(app) mongo_test = PyMongo(app, config_prefix='MONGO_TEST')
当调用初始化方法”PyMongo()”时,传入”config_prefix”参数,该PyMongo实例就会使用以”MONGO_TEST”为前缀的配置项,而不是默认的”MONGO”前缀,比如上例中的”MONGO_TEST_URI”。
添加数据
user = {'name':'Michael', 'age':18, 'scores':[{'course': 'Math', 'score': 76}]} mongo.db.users.insert_one(user)
“mongo.db.users”用来获取名为”users”集合对象,类型是”pymongo.collection.Collection”,该对象上的”insert_one()”方法用来创建一条记录。相应的,集合对象上的”insert_many()”方法可以同时创建多条记录,比如:
result = mongo.db.tests.insert_many([{'num': i} for i in range(3)])
查询数据
集合对象提供了”find_one()”和”find()”方法分别用来获取一条和多条文档记录,两个方法都可以传入查询条件作为参数:
@app.route('/user') @app.route('/user/<string:name>') def user(name=None): if name is None: users = mongo.db.users.find() return render_template('users.html', users=users) else: user = mongo.db.users.find_one({'name': name}) if user is not None: return render_template('users.html', users=[user]) else: return 'No user found!'
上例中的模板文件”users.html”如下:
<!doctype html> <title>PyMongo Sample</title> <h1>Users:</h1> <ul> {% for user in users %} <li>{{ user.name }}, {{ user.age }}</li> <ul> {% for score in user.scores %} <li>{{ score.course }}, {{ score.score }}</li> {% endfor %} </ul> {% endfor %} </ul>
“find_one()”方法返回的就是一个字典,所以我们可以直接对其作操作。”find()”方法返回的其实是一个”pymongo.cursor.Cursor”对象,不过Cursor类实现了”__iter__()”和”next()”方法,因此可以用”for … in …”循环来遍历它。
Cursor类还提供了很多功能接口来强化查询功能
- “count()”方法, 获取返回数据集的大小
users = mongo.db.users.find({'age':{'$lt':20}}) print users.count() # 打印年龄小于20的用户个数
- “sort()”方法, 排序
from flask_pymongo import DESCENDING # 返回所有用户,并按名字升序排序 users = mongo.db.users.find().sort('name') # 返回所有用户,并按年龄降序排序 users = mongo.db.users.find().sort('age', DESCENDING)
- “limit()”和”skip()”方法, 分页
# 最多只返回5条记录,并且忽略开始的2条 # 即返回第三到第七(如果存在的话)条记录 users = mongo.db.users.find().limit(5).skip(2)
- “distinct()”方法, 获取某一字段的唯一值
ages = mongo.db.users.find().distinct('age') print (ages) # 打印 [18, 21, 17]
注意,”distinct()”方法需传入字段名,它返回的是一个列表,而不是Cursor或文档。上例列出了’age’字段所有的唯一值。
更新数据
“pymongo.collection.Collection”提供了两种更新数据的方法,一种是update,可以更新指定文档中某个字段的值,同关系型数据库中的update类似。update有两个函数,”update_one()”更新一条记录,”update_many()”更新多条记录:
# 找到名为Tom的第一条记录,将其年龄加3 result = mongo.db.users.update_one({'name': 'Tom'}, {'$inc': {'age': 3}}) # 打印被改动过的记录数 print '%d records modified' % result.modified_count # 找到所有年龄小于20的用户记录,将其年龄设为20 result = mongo.db.users.update_many({'age':{'$lt':20}}, {'$set': {'age': 20}}) # 打印被改动过的记录数 print '%d records modified' % result.modified_count
另一种更新数据的方法是replace,它不是用来更新某一字段,而是把整条记录替换掉。它就一个函数”replace_one()”:
user = {'name':'Lisa', 'age':23, 'scores':[{'course': 'Politics', 'score': 95}]} # 找到名为Jane的第一条记录,将其替换为上面的名为Lisa的记录 result = mongo.db.users.replace_one({'name': 'Jane'}, user) # 打印被改动过的记录数 print '%d records modified' % result.modified_count
删除数据
删除数据可以使用集合对象上的delete方法,它也有两个函数,”delete_one()”删除一条记录,”delete_many()”删除多条记录:
# 删除名为Michael的第一条记录 result = mongo.db.users.delete_one({'name': 'Michael'}) # 打印被删除的记录数 print '%d records deleted' % result.deleted_count # 找到所有年龄大于20的用户记录 result = mongo.db.users.delete_many({'age':{'$gt':20}}) # 打印被删除的记录数 print '%d records deleted' % result.deleted_count
如果你想将集合整个删除,可以使用”drop()”方法:
mongo.db.users.drop()
练习:PyMongo结合Restful
from flask import Flask, request from flask_restful import Api, Resource from flask_pymongo import PyMongo app = Flask(__name__) app.config['MONGO_URI']='mongodb://localhost:27017/flask' api = Api(app) mongo = PyMongo(app) class User(Resource): def get(self, name): user = mongo.db.users.find_one({'name': name}) if user is not None: user.pop('_id') return dict(result='success', user=user) return dict(result='error', message='No record found') def delete(self, name): result = mongo.db.users.delete_one({'name': name}) count = result.deleted_count if count > 0: return dict(result='success', message='%d records deleted' % count) return dict(result='error', message='Failed to delete') def put(self, name): user = request.get_json() result = mongo.db.users.replace_one({'name': 'name'}, user) count = result.modified_count if count > 0: return dict(result='success', message='%d records modified' % count) return dict(result='error', message='Failed to modify') class UserList(Resource): def get(self): users = mongo.db.users.find() user_list = [] for user in users: user.pop('_id') user_list.append(user) return dict(result='success', userlist=user_list) def post(self): user = request.get_json() user_id = mongo.db.users.insert_one(user).inserted_id if user_id is not None: return dict(result='success', message='1 record added') return dict(result='error', message='Failed to insert') api.add_resource(UserList, '/users') api.add_resource(User, '/users/<name>') if __name__ == '__main__': app.run(host='0.0.0.0', debug=True)
这里我们使用name作为键值来查询,因为MongoDB中的id太复杂。注意,我们在输出时都会把”_id”字段去掉,因为它是”ObjectId”类型无法JSON序列化,同时如果你的数据中有日期时间类型,也要特别处理后才能被JSON序列化。