发布于 2026-01-06 0 阅读
0

Flask MongoDB Flask Rest API -第1部分- 将MongoDB与Flask结合使用 DEV的全球展示挑战赛,由Mux呈现:展示你的项目!

Flask MongoDB Flask REST API - 第一部分 - 将 MongoDB 与 Flask 结合使用

由 Mux 主办的 DEV 全球展示挑战赛:展示你的项目!

第一部分:将 MongoDB 与 Flask 结合使用

大家好!在本系列的一部分CRUD中,我们学习了如何使用 Python 创建基本的 REST API 功能list。但实际应用并非如此构建,因为如果服务器重启,或者更糟糕的是崩溃,那么存储在服务器上的所有信息都将丢失。为了解决这些问题(以及其他许多问题),我们需要使用数据库。所以,接下来我们将使用MongoDB作为我们的数据库。

如果你是从这部分开始阅读的,你可以在这里找到我们目前为止编写的所有代码

开始之前,请确保您的系统中已安装 MongoDB。如果您尚未安装,可以前往LinuxWindowsmacOS 平台进行安装。

主要有两个流行的库可以简化 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