作者选择了 自由和开源基金作为 写给捐款计划的一部分接受捐款。
介绍
在网络应用程序中,你通常需要一个数据库,这是一个有组织的数据收集。你使用数据库来存储和维护可有效地检索和操纵的持久数据。例如,在社交媒体应用程序中,你有一个数据库,其中用户数据(个人信息,帖子,评论,追随者)是以一种可以有效地操纵的方式存储的。你可以将数据添加到数据库,检索它,修改它或删除它,取决于不同的要求和条件。在网络应用程序中,这些要求可能是用户添加新帖子,删除帖子,或删除他们的帐户,这可能或可能不会删除他们的帖子。你执行的操作来操纵数据将取决于应用程序中的特定功能。例如,你可能不想让用户添加没有标题的帖子。
Flask 是一个轻量级的 Python 网页框架,提供用于在 Python 语言中创建网页应用程序的有用的工具和功能。 MongoDB是一个通用、面向文档的 NoSQL数据库程序,使用 JSON - 类似的文档来存储数据。 与关系数据库中使用的表关系不同,JSON 类似的文档允许灵活和动态的方案,同时保持简单性。
在本教程中,您将构建一个小型Todo列表网页应用程序,展示如何使用PyMongo库,一个MongoDB数据库驱动程序,允许您在Python中与MongoDB数据库进行交互。
前提条件
- 一个本地的Python 3编程环境,请遵循在 [如何安装和设置Python 3的本地编程环境]系列(https://www.digitalocean.com/community/tutorial_series/how-to-install-and-set-up-a-local-programming-environment-for-python-3)的分布的教程。 在本教程中,我们将呼叫我们的项目目录
flask_app
. - MongoDB安装在本地机器上。 遵循 如何在Ubuntu 20.04上安装MongoDB指南来设置您的MongoDB数据库。
- 了解基本的Flask概念,如路线,视图功能和模板。 如果您不熟悉Flask,请参阅 如何使用Flask和Python创建您的第一个Web应用程序和 [如何在Flask应用程序中使用模板
步骤 1 – 设置 PyMongo 和 Flask
在此步骤中,您将安装 Flask 和 PyMongo 库。
當您的虛擬環境啟用時,使用「pip」來安裝 Flask 和 PyMongo:
1pip install Flask pymongo
一旦安装成功完成,您将在输出结束时看到一个类似于以下的行:
1[secondary_label Output]
2
3Successfully 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 服务器并创建一个集合。
步骤 2 — 连接到 MongoDB 服务器并创建集合
在此步骤中,您将使用 PyMongo 库创建一个客户端,您将使用它与您的 MongoDB 服务器进行交互,创建数据库,然后创建一个集合来存储您的 todos。
当您的编程环境启用时,打开名为app.py
的文件,在您的flask_app
目录中进行编辑:
1nano app.py
此文件将从 Flask 和 PyMongo 库导入所需的类和助手. 您将与您的 MongoDB 服务器进行交互,以创建数据库并为 todos 创建集合。
1[label flask_app/app.py]
2from flask import Flask
3from pymongo import MongoClient
4
5app = Flask(__name__)
6
7client = MongoClient('localhost', 27017)
8
9db = client.flask_db
10todos = db.todos
保存并关闭文件。
在这里,您将导入Flask
类,您将使用它创建一个名为app
的Flask应用程序实例。
你导入的MongoClient
,你使用它来创建一个MongoDB实例的客户端对象,称为客户端
,它允许你连接和与你的MongoDB服务器进行交互。
<$>[注] 注:
强烈建议您通过遵循我们在 Ubuntu 20.04 上如何保护 MongoDB 的指南(https://andsky.com/tech/tutorials/how-to-secure-mongodb-on-ubuntu-20-04)上的指南来加强 MongoDB 安装的安全性。
一旦您在 MongoDB 中启用了身份验证,您需要在创建一个MongoClient()
实例时通过额外的用户名
和密码
参数:
1client = MongoClient('localhost', 27017, username='username', password='password')
美元
然后,您可以使用客户端
实例创建一个名为flask_db
的 MongoDB 数据库,并在名为db
的变量中保存参考。
然后,您使用db
变量在flask_db
数据库中创建一个名为todos
的集合。
在MongoDB中,数据库和集合被虚假地创建,这意味着即使你运行app.py
文件,连与数据库相关的代码都不会真正执行,直到第一个文档被创建为止。您将创建一个小型的Flask应用程序,其中有一个页面,允许用户在下一步中将 todo 文档插入您的todos
集合中。一旦添加了第一个 todo 文档,您的 MongoDB 服务器上将创建flask_db
数据库和todos
集合。
若要获取当前数据库的列表,请打开新终端,并使用以下命令启动mongo
壳:
1mongo
将打开提示,您可以使用以下命令检查您的数据库:
1show dbs
如果这是MongoDB的新安装,输出将列出admin
,config
和本地
数据库。
您会注意到flask_db
尚不存在,然后在终端窗口中运行mongo
壳,然后继续到下一步。
步骤 3 — 创建一个添加和显示全部的网页
在此步骤中,您将创建一个具有 Web 表单的 Web 页面,允许用户添加 Todos,并在同一页面上显示它们。
随着您的编程环境启用,打开您的 app.py
文件进行编辑:
1nano app.py
首先,从flask
中添加以下进口:
1[label flask_app/app.py]
2from flask import Flask, render_template, request, url_for, redirect
3from pymongo import MongoClient
4
5# ...
在这里,您导入将用于渲染HTML模板的render_template()
辅助函数,用户将提交的数据访问的请求
对象, URL 生成的url_for()
函数和redirect()
函数,在添加 todo后将用户重定向回索引页面。
然后在文件末尾添加以下路径:
1[label flask_app/app.py]
2# ...
3
4@app.route('/', methods=('GET', 'POST'))
5def index():
6 return render_template('index.html')
保存并关闭文件。
在此路径中,您将GET
,POST
字符串转移到方法
参数,以允许 GET 和 POST 请求。 GET 请求用于从服务器中获取数据。 POST 请求用于将数据发送到特定路径。默认情况下,仅允许 GET 请求。当用户先使用 GET 请求请求的 /
路径时,将生成一个名为 index.html
的模板文件。当用户填写并提交 Web 表格创建新 todos时,您将稍后编辑此路线以处理 POST 请求。
接下来,在您的flask_app
目录中创建一个模板文件夹,以及您在前一条路径中提到的index.html
模板:
1mkdir templates
2nano templates/index.html
将以下代码添加到 index.html 文件中:
1[label flask_app/templates/index.html]
2<!DOCTYPE html>
3<html lang="en">
4<head>
5 <meta charset="UTF-8">
6 <title>FlaskApp</title>
7 <style>
8 .todo {
9 padding: 20px;
10 margin: 10px;
11 background-color: #eee;
12 }
13 </style>
14</head>
15<body>
16 <h1>FlaskTODO</h1>
17 <hr>
18 <div class="content">
19 <form method="post">
20 <p>
21 <b><label for="content">Todo content</label></b>
22 </p>
23 <p>
24 <input type="text" name="content"
25 placeholder="Todo Content"></input>
26 </p>
27
28 <p>
29 <b><label for="degree">Degree</label></b>
30 </p>
31 <p>
32 <input id="degree-0" name="degree" required type="radio" value="Important">
33 <label for="degree-0">Important</label>
34 </p>
35 <p>
36 <input id="degree-1" name="degree" required type="radio" value="Unimportant">
37 <label for="degree-1">Unimportant</label>
38 </p>
39 <button type="submit">Submit</button>
40 </form>
41 </div>
42</body>
43</html>
保存并关闭文件。
在 Web 表单中,您将方法
属性设置为发布
,以表示表单将提交 POST 请求。您有一个名为内容
的 todo 内容的文本输入字段,您将使用它来访问您的/
路径中的标题数据。您还具有两个名为级别
的 HTML 广播按钮,允许用户指定每个 todo 项目的重要程度:他们可以在创建 todo 时选择 重要或 不重要选项。
在您的flask_app
目录中启用虚拟环境时,请使用FLASK_APP
环境变量告诉Flask关于该应用程序(在这种情况下是app.py
) 然后将FLASK_ENV
环境变量设置为development
,以便在开发模式下运行应用程序并获取调试器的访问。有关Flask调试器的更多信息,请参阅如何处理Flask应用程序中的错误
(LINK0)。
1export FLASK_APP=app
2export FLASK_ENV=development
接下来,运行应用程序:
1flask run
<$>[注]
注:
在尝试运行应用程序时,您可能会收到一个 ModuleNotFoundError: No module named 'pymongo'
错误。
当开发服务器运行时,请使用您的浏览器访问以下URL:
1http://127.0.0.1:5000/
您将看到索引页面,其中包含 Todo 内容的输入字段、重要程度的两个无线电按钮以及一个 ** Submit** 按钮。
有关 Web 表单的更多信息,请参阅 如何在 Flask 应用程序中使用 Web 表单。 有关管理 Web 表单的更先进和更安全的方法,请参阅 如何使用和验证 Web 表单使用 Flask-WTF。
如果您填写表单并提交它,将 POST 请求发送到服务器,则不会发生任何事情,因为您没有在 /
路径上处理 POST 请求。
让服务器运行,并打开一个新的终端窗口。
打开 app.py 来处理用户提交的 POST 请求,将其添加到 todos 集合中,并在索引页面上显示:
1nano app.py
编辑/
路线以显示如下:
1[label flask_app/app.py]
2
3@app.route('/', methods=('GET', 'POST'))
4def index():
5 if request.method=='POST':
6 content = request.form['content']
7 degree = request.form['degree']
8 todos.insert_one({'content': content, 'degree': degree})
9 return redirect(url_for('index'))
10
11 all_todos = todos.find()
12 return render_template('index.html', todos=all_todos)
保存并关闭文件。
在这些更改中,您处理if request.method ==
POST``条件内的 POST 请求,您从request.form
对象中提交的 todo 内容和重要程度。
您在 Python 字典中提供 todo 数据,将内容
设置为用户在 todo 内容文本中提交的值,并将度
键设置为用户选择的无线电按钮的值。
要显示所有保存的 todos,您可以使用负责处理 POST 请求的代码之外的 find()
方法,该方法会返回所有在 todos
集合中可用的 todo 文档。 您将从数据库中获取的 todos 保存到名为 all_todos
的变量中,然后编辑 render_template()
函数调用以将 todo 文档列表传送到 index.html
模板中,该模板将以名为 todos
的变量提供。
如果您更新索引页面,您可能会收到浏览器的消息,要求您确认重新提交表单. 如果您接受,您之前提交的Todo项目在处理POST请求之前将被添加到数据库中,因为处理表单的代码现在存在于路线中。
由于索引页面还没有显示 todo 项目的代码,所以您添加的项目将不可见. 如果您允许浏览器重新提交表单,您可以通过打开 mongo 壳并使用以下命令连接到 flask_db
数据库来查看新添加的数据:
1use flask_db
然后使用find()
函数来获取数据库中的所有 todo 项目:
1db.todos.find()
如果任何数据被重新提交,您将在您的输出中看到它。
接下来,打开index.html
模板以显示您传递给它的todos
列表的内容:
1nano templates/index.html
通过在表单后添加一个 <hr>
间断和一个 Jinja for
循环来编辑文件,使文件看起来如下:
1[label flask_app/templates/index.html]
2<!DOCTYPE html>
3<html lang="en">
4<head>
5 <meta charset="UTF-8">
6 <title>FlaskApp</title>
7 <style>
8 .todo {
9 padding: 20px;
10 margin: 10px;
11 background-color: #eee;
12 }
13 </style>
14</head>
15<body>
16 <h1>FlaskTODO</h1>
17 <hr>
18 <div class="content">
19 <form method="post">
20 <p>
21 <b><label for="content">Todo content</label></b>
22 </p>
23 <p>
24 <input type="text" name="content"
25 placeholder="Todo Content"></input>
26 </p>
27
28 <p>
29 <b><label for="degree">Degree</label></b>
30 </p>
31 <p>
32 <input id="degree-0" name="degree" required type="radio" value="Important">
33 <label for="degree-0">Important</label>
34 </p>
35 <p>
36 <input id="degree-1" name="degree" required type="radio" value="Unimportant">
37 <label for="degree-1">Unimportant</label>
38 </p>
39 <button type="submit">Submit</button>
40 </form>
41 <hr>
42 {% for todo in todos %}
43 <div class="todo">
44 <p>{{ todo['content'] }} <i>({{ todo['degree']}})</i></p>
45 </div>
46 {% endfor %}
47
48 </div>
49</body>
50</html>
保存并关闭文件。
在此文件中,您添加一个<hr>
标签来分离网页表单和 todos列表。
您在行中使用for
循环{% for todo in todos %}
来浏览todos
列表中的每个 todo 项目. 您在<p>
标签中显示 todo 内容和重要程度。
现在更新您的索引页面,填写网页表格,并提交它. 您将看到您在表单下添加的 todo. 接下来,您将添加一个按钮,允许用户删除现有的 todos。
步骤 4 - 删除所有
在此步骤中,您将添加一条路线,允许用户使用按钮删除 todos。
首先,您将添加一个新的/id/delete
路径,该路径接受 POST 请求. 您的新的delete()
视图函数将收到从 URL 删除的 todo ID,然后使用该 ID 删除它。
要删除一个 todo,你将其 ID 作为一个字符串,你必须将其转换为 ObjectId,然后将其传输到收藏的删除方法,所以你需要从处理BSON(二进制JSON)编码和解码的 bson
模块中导入 ObjectId()
类。
打开app.py
来编辑:
1nano app.py
首先,在文件的顶部添加以下导入:
1[label flask_app/app.py]
2from bson.objectid import ObjectId
3
4# ...
这是您将使用的 ObjectId()
类来将字符串 ID 转换为 ObjectId 对象。
然后在末尾添加以下路线:
1[label flask_app/app.py]
2
3# ...
4
5@app.post('/<id>/delete/')
6def delete(id):
7 todos.delete_one({"_id": ObjectId(id)})
8 return redirect(url_for('index'))
保存并关闭文件。
在这里,您使用的是 Flask 版本 2.0.0中引入的 app.post]([Flask 版本 2.0.0])(https://flask.palletsprojects.com/en/2.0.x/changes/#version-2-0-0)),它为常见的 HTTP 方法添加了捷径,例如, @app.post("/login")' 是
@app.route("/login", methods=["POST"])' 的捷径,这意味着此视图只接受 POST 请求,并且在您的浏览器上导航到 /ID/delete
路径将返回 405 方法不允许
错误,因为 Web 浏览器默认为 GET 请求。 为了删除 todo,用户点击发送 POST 请求到该路
该函数接收要删除的 todo 文档的 ID. 您将该 ID 传输到 todos
集合中的 delete_one()
方法,并使用您之前导入的 ObjectId()
类将您接收的 string ID 转换为 ObjectId。
删除 todo 文档后,您将用户重定向到索引页面。
接下来,编辑index.html
模板以添加一个 Delete Todo按钮:
1nano templates/index.html
通过添加一个新的<form>
标签来编辑for
循环:
1[label flask_app/templates/index.html]
2
3 {% for todo in todos %}
4 <div class="todo">
5 <p>{{ todo['content'] }} <i>({{ todo['degree']}})</i></p>
6 <form method="POST" action="{{ url_for('delete', id=todo['_id']) }}" >
7 <input type="submit" value="Delete Todo"
8 onclick="return confirm('Are you sure you want to delete this entry?')">
9 </form>
10 </div>
11 {% endfor %}
保存并关闭文件。
在这里,你有一个网页表格,将POST请求提交到删除()
视图函数中。 您通过todo['_id']
来指定将被删除的 todo。 您使用在网页浏览器中可用的 confirm()
方法在提交请求之前显示确认消息。
现在刷新你的索引页面,你会看到一个 删除 Todo按钮在每个 Todo 项目下面. 点击它,并确认删除。
现在你有办法从你的mongoDB数据库中删除不必要的 todos在你的Flask应用程序。
要确认删除,请打开您的mongo壳并使用find()
函数:
1db.todos.find()
您应该看到您删除的项目已不在您的todos
集合中。
结论
你建立了一个小型的 Flask Web 应用程序来管理与 MongoDB 数据库通信的 todos. 你学会了如何连接到 MongoDB 数据库服务器,创建存储一组文档的集合,将数据插入到集合中,并从集合中获取和删除数据。
如果您想了解更多关于 Flask 的信息,请参阅 如何使用 Flask 创建网站系列的其他教程。
有关 MongoDB 的更多信息,请参阅我们的 如何使用 MongoDB 管理数据 教程系列。