Flask MongoDB Flask REST API - 第一部分 - 将 MongoDB 与 Flask 结合使用
由 Mux 主办的 DEV 全球展示挑战赛:展示你的项目!
第一部分:将 MongoDB 与 Flask 结合使用
大家好!在本系列的上一部分CRUD中,我们学习了如何使用 Python 创建基本的 REST API 功能list。但实际应用并非如此构建,因为如果服务器重启,或者更糟糕的是崩溃,那么存储在服务器上的所有信息都将丢失。为了解决这些问题(以及其他许多问题),我们需要使用数据库。所以,接下来我们将使用MongoDB作为我们的数据库。
如果你是从这部分开始阅读的,你可以在这里找到我们目前为止编写的所有代码。
开始之前,请确保您的系统中已安装 MongoDB。如果您尚未安装,可以前往Linux、Windows和macOS 平台进行安装。
主要有两个流行的库可以简化 MongoDB 的使用:
1) Pymongo是 MongoDB 的一个底层 Python 封装,使用它Pymongo类似于直接编写 MongoDB 查询。以下是一个简单的示例,演示如何使用Pymongo 更新与给定条件匹配
的电影名称。ididPymongo
db['movies'].update({'_id': id},
{'$set': {'name': 'My new title'}})
Pymongo它不使用任何预定义的模式,因此可以充分利用 MongoDB 的无模式特性。
2) MongoEngine是一个对象-文档映射器,它使用文档模式,使 MongoDB 的操作更加清晰便捷。
以下是使用 MongoEngine 的相同示例mongoengine。
Movies.objects(id=id).update(name='My new title')
Mongoengine它使用预定义的数据库字段模式,这限制了它利用 MongoDB 的无模式特性。
正如我们所见,双方各有优缺点。因此,请选择最适合您项目的方案。在本系列文章中,我们将学习…… Mongoengine,如果您也希望我讲解其他内容,请在下方评论区留言Pymongo。
Mongoengine为了更好地在我们的应用程序中使用它,Flask有一个名为Flask-MongengineFlask的优秀扩展。
那么,让我们开始安装吧flask-mongoengine。
pipenv install flask-mongoengine
注意:由于flask-mongoengineflask-mongoengine构建于 之上mongoengine,因此在安装 flask-mongoengine 时会自动安装它;而 flask-mongoengine 也mongoengine构建于 之上pymongo,因此它也会同时安装。
现在,让我们在文件夹内创建一个新文件夹movie-bag。我把它命名为database。在database文件夹内创建一个名为的文件db.py。另外,再创建一个名为的文件。models.py
让我们看看文件/文件夹现在的样子。
movie-bag
│ app.py
| Pipfile
| Pipfile.lock
└───database
│ db.py
└───models.py
现在,让我们进入精彩的部分。
首先,让我们通过将以下代码添加到我们的代码中来初始化数据库。db.py
#~movie-bag/database/db.py
from flask_mongoengine import MongoEngine
db = MongoEngine()
def initialize_db(app):
db.init_app(app)
在这里,我们导入MongoEngine并创建了db对象,并定义了一个函数initialize_db(),我们将从我们的代码中调用该函数app.py来初始化数据库。
movie.py让我们在内部models目录中编写以下代码。
#~movie-bag/database/models.py
from .db import db
class Movie(db.Document):
name = db.StringField(required=True, unique=True)
casts = db.ListField(db.StringField(), required=True)
genres = db.ListField(db.StringField(), required=True)
我们刚刚创建的是数据库文档。这样,用户就无法添加此处未定义的字段。
这里我们可以看到,该Movie文档包含三个字段:
1) name:这是一个类型为 的字段String,我们还对该字段设置了两个约束。-
这required意味着用户不能在未提供电影标题的情况下创建新电影。-
这unique意味着电影名称必须唯一且不能重复。
2) casts:是一个类型为的字段list,其中包含类型的值String
3)genres同上casts
最后,我们可以初始化数据库app.py,并修改我们的view函数(处理 API 请求的函数)以使用Movie我们之前定义的文档。
#~movie-bag/app.py
-from flask import Flask, jsonify, request
+from flask import Flask, request, Response
+from database.db import initialize_db
+from database.models import Movie
app = Flask(__name__)
-movies = [
- {
- "name": "The Shawshank Redemption",
- "casts": ["Tim Robbins", "Morgan Freeman", "Bob Gunton", "William Sadler"],
- "genres": ["Drama"]
- },
- {
- "name": "The Godfather ",
- "casts": ["Marlon Brando", "Al Pacino", "James Caan", "Diane Keaton"],
- "genres": ["Crime", "Drama"]
- }
-]
+app.config['MONGODB_SETTINGS'] = {
+ 'host': 'mongodb://localhost/movie-bag'
+}
+
+initialize_db(app)
-@app.route('/movies')
-def hello():
- return jsonify(movies)
+@app.route('/movies')
+def get_movies():
+ movies = Movie.objects().to_json()
+ return Response(movies, mimetype="application/json", status=200)
-@app.route('/movies', methods=['POST'])
-def add_movie():
- movie = request.get_json()
- movies.append(movie)
- return {'id': len(movies)}, 200
+@app.route('/movies', methods=['POST'])
+ body = request.get_json()
+ movie = Movie(**body).save()
+ id = movie.id
+ return {'id': str(id)}, 200
-@app.route('/movies/<int:index>', methods=['PUT'])
-def update_movie(index):
- movie = request.get_json()
- movies[index] = movie
- return jsonify(movies[index]), 200
+@app.route('/movies/<id>', methods=['PUT'])
+def update_movie(id):
+ body = request.get_json()
+ Movie.objects.get(id=id).update(**body)
+ return '', 200
-@app.route('/movies/<int:index>', methods=['DELETE'])
-def delete_movie(index):
- movies.pop(index)
- return 'None', 200
+@app.route('/movies/<id>', methods=['DELETE'])
+def delete_movie(id):
+ Movie.objects.get(id=id).delete()
+ return '', 200
app.run()
哇!变化真大,我们一步一步来吧。
-from flask import Flask, jsonify, request
+from flask import Flask, request, Response
+from database.db import initialize_db
+from database.models.movie import Movie
这里我们移除了jsonify不再需要的部分,并添加了Response用于设置响应类型的部分。然后我们导入了之前定义的initialize_db表单db.py来初始化数据库。最后,我们导入了Movie文档表单。movie.py
+app.config['MONGODB_SETTINGS'] = {
+ 'host': 'mongodb://localhost/movie-bag'
+}
+
+db = initialize_db(app)
这里我们配置 MongoDB 数据库。主机名格式为 `<host>` <host-url>/<database-name>。由于我们已将 MongoDB 安装在本地,因此可以通过 `<host>` 访问它mongodb://localhost/,我们将数据库命名为 `<database_name>` movie-bag。
最后,我们初始化数据库。
+@app.route('/movies')
+def get_movies():
+ movies = Movie.objects().to_json()
+ return Response(movies, mimetype="application/json", status=200)
+
Movie这里我们使用从文档中获取所有对象,并使用Movies.objects()将它们转换为。最后,我们返回一个对象,其中我们将响应类型定义为。JSONto_json()Responseapplication/json
+@app.route('/movies', methods=['POST'])
+ body = request.get_json()
+ movie = Movie(**body).save()
+ id = movie.id
+ return {'id': str(id)}, 200
在POST请求中,我们首先获取JSON要发送的参数以及请求本身。然后,我们使用 ` Movieload` 语句将请求中的字段加载到文档中Movie(**body)。这里**`load` 被称为扩展运算符,...在 JavaScript 中写作 `($($($($($($($($($($($($($($($($($( ))))`(如果您熟悉 JavaScript)”)。顾名思义,它的作用是展开对象。dict因此
,`($($($($($($($($($($($($($($ ($($($($($( ) ...Movie(**body)
Movie(name="Name of the movie",
casts=["a caste"],
genres=["a genre"])
最后,我们保存文档并获取其id内容,然后将其作为响应返回。
+@app.route('/movies/<id>', methods=['PUT'])
+def update_movie(id):
+ body = request.get_json()
+ Movie.objects.get(id=id).update(**body)
+ return '', 200
首先,我们找到id与请求中发送的电影文档匹配的文档,然后对其进行更新。这里我们也使用了扩展运算符将值传递给update()函数。
+@app.route('/movies/<id>', methods=['DELETE'])
+def delete_movie(id):
+ Movie.objects.get(id=id).delete()
+ return '', 200
与此类似,update_movie()我们获取与给定电影文档匹配id并将其从数据库中删除。
哦,我刚想起来我们还没有把 API 端点添加到GET服务器上的单个文档中。
我们来添加一下:
在上面添加以下代码。app.run()
@app.route('/movies/<id>')
def get_movie(id):
movies = Movie.objects.get(id=id).to_json()
return Response(movies, mimetype="application/json", status=200)
现在您可以通过 API 端点获取单部电影/movies/<valid_id>。
要运行服务器,请确保您位于该movie-bag目录中。
然后运行
pipenv shell
python app.py
在终端中激活虚拟环境并启动服务器。
哇!恭喜你走到这一步。要测试 API,请使用Postman与本系列前一部分中相同的方法。
您可能已经注意到,如果我们向端点发送无效数据(例如缺少名称或其他字段),我们会收到一个不友好的错误信息HTML。如果我们尝试获取id数据库中不存在的电影文档,也会收到一个不友好的错误HTML响应。这并非一个设计良好的 API 应有的行为。我们将在本系列的后续部分学习如何处理此类错误。
我们从本系列的这一部分中学到了什么?
Pymongo和之间的区别Mongoengine。- 如何使用
Mongoengine.创建文档架构 - 如何使用.执行
CRUD操作Mongoengine - Python 扩展运算符。
您可以在这里找到这部分的完整代码。
在下一部分中,我们将学习如何使用 Flask 更好地构建应用程序结构Blueprint,以及如何遵循最佳实践,以最少的配置更快地创建 REST API。flask-restful
祝您编程愉快😊
文章来源:https://dev.to/paurakhsharma/flask-rest-api-part-1-using-mongodb-with-flask-3g7d