如何在 Flask 应用程序中使用 MongoDB
作者选择自由和开源基金作为Write for DOnations计划的一部分来接受捐赠。
简介
在 Web 应用程序中,您通常需要一个数据库,它是一个有组织的数据集合。您使用数据库来存储和维护可以有效检索和操作的持久数据。例如,在社交媒体应用程序中,您有一个数据库,其中用户数据(个人信息、帖子、评论、关注者)以一种可以有效操作的方式存储。您可以根据不同的要求和条件,将数据添加到数据库、检索、修改或删除数据库。在 Web 应用程序中,这些要求可能是用户添加新帖子、删除帖子或删除他们的帐户,这可能会也可能不会删除他们的帖子。您为操作数据而执行的操作将取决于应用程序中的特定功能。例如,您可能不希望用户添加没有标题的帖子。
Flask 是一个轻量级的 Python Web 框架,它提供了有用的工具和功能来用 Python 语言创建 Web 应用程序。MongoDB是一个通用的、面向文档的NoSQL数据库程序,它使用JSON类文档来存储数据。与关系数据库中使用的表格关系不同,类似 JSON 的文档允许灵活和动态的模式,同时保持简单性。一般来说,NoSQL 数据库具有水平扩展的能力,使其适用于大数据和实时应用程序。
在本教程中,您将构建一个小型待办事项列表 Web 应用程序,演示如何使用PyMongo库,这是一个 MongoDB 数据库驱动程序,允许您在 Python 中与 MongoDB 数据库进行交互。您将使用它与 Flask 一起执行基本任务,例如连接到数据库服务器、创建在 MongoDB 中存储一组文档的集合、将数据插入集合以及从集合中检索和删除数据。
先决条件
-
本地 Python 3 编程环境,按照如何为 Python 3系列安装和设置本地编程环境中的教程进行分发。在本教程中,我们将调用我们的项目目录
flask_app。 -
MongoDB 安装在本地机器上。按照如何在 Ubuntu 20.04 上安装 MongoDB 指南设置您的 MongoDB 数据库。
-
了解基本的 Flask 概念,例如路由、视图函数和模板。如果您不熟悉 Flask,请查看如何使用 Flask 和 Python 创建您的第一个 Web 应用程序和如何在 Flask 应用程序中使用模板。
-
了解基本的 HTML 概念。您可以查看我们的如何使用 HTML 构建网站教程系列以了解背景知识。
第一步——设置 PyMongo 和 Flask
在这一步中,您将安装 Flask 和 PyMongo 库。
激活虚拟环境后,使用pip安装 Flask 和 PyMongo:
pip install Flask pymongo
安装成功完成后,您将在输出末尾看到类似于以下内容的行:
Output
Successfully installed Flask-2.0.2 Jinja2-3.0.3 MarkupSafe-2.0.1 Werkzeug-2.0.2 click-8.0.3 itsdangerous-2.0.1 pymongo-4.0.1
现在您已经安装了所需的 Python 包,您将连接到 MongoDB 服务器并创建一个集合。
第二步——连接MongoDB服务器并创建集合
在这一步中,您将使用 PyMongo 库创建一个客户端,用于与 MongoDB 服务器交互、创建数据库,然后创建一个集合来存储您的待办事项。
激活编程环境后,在flask_app目录中打开一个名为app.py的文件进行编辑:
nano app.py
该文件将从 Flask 和 PyMongo 库中导入必要的类和助手。您将与 MongoDB 服务器交互以创建数据库并为待办事项创建集合。在app.py中加入如下代码:
烧瓶_app/app.py
from flask import Flask
from pymongo import MongoClient
app = Flask(__name__)
client = MongoClient('localhost', 27017)
db = client.flask_db
todos = db.todos
保存并关闭文件。
在这里您导入Flask类,您可以使用它来创建一个名为app的 Flask 应用程序实例。
您导入MongoClient用于为名为client的 MongoDB 实例创建客户端对象,它允许您连接 MongoDB 服务器并与之交互。当您实例化MongoClient()时,您将 MongoDB 服务器的主机(在我们的示例中为localhost)和端口(此处为27017)传递给它。
笔记:
强烈建议您按照我们关于如何在 Ubuntu 20.04上保护 MongoDB 的指南来加强 MongoDB 安装的安全性。一旦它得到保护,您就可以将配置为 MongoDB 以接受远程连接。
在 MongoDB 中启用身份验证后,您需要在创建MongoClient()实例时传递额外的username和password参数,如下所示:
client = MongoClient('localhost', 27017, username='username', password='password')
然后使用client实例创建一个名为flask_db的 MongoDB 数据库,并将对它的引用保存在名为db的变量中。
然后使用db变量在flask_db数据库上创建一个名为todos的集合。集合在 MongoDB 中存储一组文档,就像关系数据库中的表一样。
在 MongoDB 中,数据库和集合是惰性创建的。这意味着即使执行app.py文件,在创建第一个文档之前,不会真正执行与数据库相关的代码。您将创建一个带有页面的小型 Flask 应用程序,该页面允许用户在下一步中将 todo 文档插入到您的todos集合中。添加第一个 todo 文档后,flask_db数据库和todos集合将在您的 MongoDB 服务器上创建。
要获取当前数据库的列表,请打开一个新终端,然后使用以下命令启动mongoshell:
mongo
将打开一个提示,您可以使用以下命令检查您的数据库:
show dbs
如果这是新安装的 MongoDB,输出将列出admin、config和local数据库。
你会注意到flask_db还不存在。让mongoshell 在终端窗口中运行并继续下一步。
第 3 步 — 创建用于添加和显示待办事项的网页
在这一步中,您将创建一个带有 Web 表单的网页,该表单允许用户添加待办事项,并将它们显示在同一页面上。
激活编程环境后,打开app.py文件进行编辑:
nano app.py
首先,从flask添加以下导入:
烧瓶_app/app.py
from flask import Flask, render_template, request, url_for, redirect
from pymongo import MongoClient
# ...
在这里,您导入用于呈现 HTML 模板的render_template()辅助函数、用于访问用户将提交的数据的request对象、用于生成 URL 的url_for()函数以及用于将用户重定向回索引页面后的redirect()函数添加待办事项。
然后在文件末尾添加以下路由:
烧瓶_app/app.py
# ...
@app.route('/', methods=('GET', 'POST'))
def index():
return render_template('index.html')
保存并关闭文件。
在此路由中,您将元组('GET', 'POST')传递给methods参数以允许 GET 和 POST 请求。 GET 请求用于从服务器检索数据。 POST 请求用于将数据发布到特定路由。默认情况下,只允许 GET 请求。当用户第一次使用 GET 请求请求/路由时,将呈现一个名为index.html的模板文件。您稍后将编辑此路由以处理用户填写和提交 Web 表单以创建新待办事项时的 POST 请求。
接下来在您的flask_app目录中创建一个模板文件夹,以及您在前面的路线中引用的index.html模板:
mkdir templates
nano templates/index.html
在index.html文件中添加以下代码:
烧瓶_app/templates/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>FlaskApp</title>
<style>
.todo {
padding: 20px;
margin: 10px;
background-color: #eee;
}
</style>
</head>
<body>
<h1>FlaskTODO</h1>
<hr>
<div class="content">
<form method="post">
<p>
<b><label for="content">Todo content</label></b>
</p>
<p>
<input type="text" name="content"
placeholder="Todo Content"></input>
</p>
<p>
<b><label for="degree">Degree</label></b>
</p>
<p>
<input id="degree-0" name="degree" required type="radio" value="Important">
<label for="degree-0">Important</label>
</p>
<p>
<input id="degree-1" name="degree" required type="radio" value="Unimportant">
<label for="degree-1">Unimportant</label>
</p>
<button type="submit">Submit</button>
</form>
</div>
</body>
</html>
保存并关闭文件。
在这里,您有一个带有标题、一些样式、标题和 Web 表单的基本 HTML 页面。在 Web 表单中,您将method属性设置为post以指示该表单将提交 POST 请求。您有一个名为content的待办事项内容的文本输入字段,您将使用它来访问/路由中的标题数据。您还有两个名为degree的 HTML 单选按钮,允许用户指定每个待办事项的重要程度:他们可以在创建待办事项时选择 Important 选项或 Unimportant 选项.最后,表单末尾有一个 Submit 按钮。
在激活虚拟环境的flask_app目录中,使用FLASK_APP环境变量告诉 Flask 应用程序(在本例中为app.py)。然后将FLASK_ENV环境变量设置为development以在开发模式下运行应用程序并访问调试器。有关 Flask 调试器的更多信息,请参阅如何处理 Flask 应用程序中的错误。使用以下命令执行此操作:
export FLASK_APP=app
export FLASK_ENV=development
接下来,运行应用程序:
flask run
注意: 在尝试运行应用程序时,您可能会收到ModuleNotFoundError: No module named 'pymongo'错误。要解决此问题,请停用您的虚拟环境并重新激活它。然后再次运行flask run命令。
在开发服务器运行的情况下,使用浏览器访问以下 URL:
http://127.0.0.1:5000/
您将看到索引页面,其中包含待办事项内容的输入字段、重要程度的两个单选按钮和一个提交按钮。

有关 Web 表单的更多信息,请参阅如何在 Flask 应用程序中使用 Web 表单。有关管理 Web 表单的更高级和更安全的方法,请参阅How To Use and Validate Web Forms with Flask-WTF。
如果您填写并提交表单,向服务器发送 POST 请求,则不会发生任何事情,因为您没有处理/路由上的 POST 请求。
保持服务器运行并打开一个新的终端窗口。
打开app.py处理用户提交的POST请求,添加到todos集合中,并在index页面展示:
nano app.py
编辑/路由,如下所示:
烧瓶_app/app.py
@app.route('/', methods=('GET', 'POST'))
def index():
if request.method=='POST':
content = request.form['content']
degree = request.form['degree']
todos.insert_one({'content': content, 'degree': degree})
return redirect(url_for('index'))
all_todos = todos.find()
return render_template('index.html', todos=all_todos)
保存并关闭文件。
在这些更改中,您在if request.method == 'POST'条件内处理 POST 请求。您从request.form对象中提取用户提交的待办事项内容和重要程度。
您在 todos 集合上使用insert_one()方法将 todo 文档添加到其中。您在 Python 字典中提供 todo 数据,将'content'设置为用户在 todo 内容的文本字段中提交的值,并将'degree'键设置为用户选择的单选按钮的值。然后重定向到索引页面,该页面将刷新页面并显示新添加的待办事项。
要显示所有保存的待办事项,请在负责处理 POST 请求的代码之外使用find()方法,该方法返回todos集合中可用的所有待办事项文档。您将从数据库中获得的待办事项保存在名为all_todos的变量中,然后编辑render_template()函数调用以将待办事项文档列表传递给index.html模板,该模板将在模板中名为todos的变量中可用。
如果刷新索引页面,您可能会收到来自浏览器的消息,要求您确认重新提交表单。如果您接受,您之前在处理 POST 请求之前提交的待办事项将被添加到数据库中,因为处理表单的代码现在存在于路由中。
因为索引页面还没有显示待办事项的代码,所以您添加的项目将不可见。如果您允许浏览器重新提交表单,您可以通过打开 mongo shell 并使用以下命令连接到flask_db数据库来查看新添加的数据:
use flask_db
然后使用find()函数获取数据库中的所有待办事项:
db.todos.find()
如果重新提交了任何数据,您将在输出中看到它。
接下来,打开index.html模板以显示您传递给它的todos列表的内容:
nano templates/index.html
编辑文件,在表格后添加<hr>中断和Jinjafor循环,使文件如下所示:
烧瓶_app/templates/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>FlaskApp</title>
<style>
.todo {
padding: 20px;
margin: 10px;
background-color: #eee;
}
</style>
</head>
<body>
<h1>FlaskTODO</h1>
<hr>
<div class="content">
<form method="post">
<p>
<b><label for="content">Todo content</label></b>
</p>
<p>
<input type="text" name="content"
placeholder="Todo Content"></input>
</p>
<p>
<b><label for="degree">Degree</label></b>
</p>
<p>
<input id="degree-0" name="degree" required type="radio" value="Important">
<label for="degree-0">Important</label>
</p>
<p>
<input id="degree-1" name="degree" required type="radio" value="Unimportant">
<label for="degree-1">Unimportant</label>
</p>
<button type="submit">Submit</button>
</form>
<hr>
{% for todo in todos %}
<div class="todo">
<p>{{ todo['content'] }} <i>({{ todo['degree']}})</i></p>
</div>
{% endfor %}
</div>
</body>
</html>
保存并关闭文件。
在此文件中,您添加一个<hr>标记来分隔 Web 表单和待办事项列表。
您在{% for todo in todos %}行中使用for循环遍历todos列表中的每个待办事项。您在<p>标签内显示待办事项内容和重要程度。
现在刷新您的索引页面,填写网络表单,然后提交。您将在表单下方看到您添加的待办事项。接下来,您将添加一个按钮以允许用户删除现有的待办事项。
第四步——删除待办事项
在这一步中,您将添加一个允许用户使用按钮删除待办事项的路由。
首先,您将添加一个接受 POST 请求的新/id/delete路由。您的新delete()视图函数将从 URL 中接收要删除的待办事项的 ID,然后使用该 ID 将其删除。
要删除待办事项,您需要将其 ID 作为字符串获取,并且必须将其转换为ObjectId,然后再将其传递给集合的删除方法。所以你需要从bson模块中导入ObjectId()类,该模块处理 BSON(二进制 JSON)编码和解码。
打开app.py进行编辑:
nano app.py
首先,在文件顶部添加以下导入:
烧瓶_app/app.py
from bson.objectid import ObjectId
# ...
这是您将用于将字符串 ID 转换为 ObjectId 对象的ObjectId()类。
然后在最后添加以下路由:
烧瓶_app/app.py
# ...
@app.post('/<id>/delete/')
def delete(id):
todos.delete_one({"_id": ObjectId(id)})
return redirect(url_for('index'))
保存并关闭文件。
在这里,不是使用通常的app.route装饰器,而是使用Flask 版本 2.0.0中引入的app.post装饰器,它为常见的 HTTP 方法添加了快捷方式。例如,@app.post("/login")是@app.route("/login", methods=["POST"])的快捷方式。这意味着这个视图函数只接受 POST 请求,并且在浏览器上导航到/ID/delete路由会返回405 Method Not Allowed错误,因为 Web 浏览器默认使用 GET 请求。要删除待办事项,用户单击向该路由发送 POST 请求的按钮。
该函数接收要删除的待办事项文档的 ID。将此 ID 传递给todos集合上的delete_one()方法,然后使用之前导入的ObjectId()类将收到的字符串 ID 转换为 ObjectId。
删除待办事项文档后,将用户重定向到索引页面。
接下来,编辑index.html模板以添加一个 Delete Todo 按钮:
nano templates/index.html
通过添加一个新的<form>标签来编辑for循环:
烧瓶_app/templates/index.html
{% for todo in todos %}
<div class="todo">
<p>{{ todo['content'] }} <i>({{ todo['degree']}})</i></p>
<form method="POST" action="{{ url_for('delete', id=todo['_id']) }}" >
<input type="submit" value="Delete Todo"
onclick="return confirm('Are you sure you want to delete this entry?')">
</form>
</div>
{% endfor %}
保存并关闭文件。
在这里,您有一个向delete()视图函数提交 POST 请求的 Web 表单。您通过todo zwz100187 '_id']指定将被删除的待办事项。在提交请求之前,您可以使用 Web 浏览器中可用的 confirm()方法显示确认消息。
现在刷新您的索引页面,您会在每个待办事项下方看到一个删除待办事项按钮。单击它,然后确认删除。您将被重定向到索引页面,待办事项将不再存在。
您现在可以在 Flask 应用程序中从 mongoDB 数据库中删除不需要的待办事项。
要确认删除,请打开您的 mongo shell 并使用find()函数:
db.todos.find()
您应该会看到您已删除的项目不再在您的todos集合中。
结论
您构建了一个小型 Flask Web 应用程序,用于管理与 MongoDB 数据库通信的待办事项。您学习了如何连接到 MongoDB 数据库服务器、创建存储一组文档的集合、将数据插入集合以及从集合中检索和删除数据。
如果您想了解更多关于 Flask 的信息,请查看如何使用 Flask系列创建网站中的其他教程。
有关 MongoDB 的更多信息,请参阅我们的如何使用 MongoDB 管理数据教程系列。
更多推荐

所有评论(0)