作者选择了自由开源基金作为为捐赠而写计划的一部分来接受捐赠。
介绍
在网络应用中,通常需要使用数据库,它是一个组织良好的数据集合。您使用数据库来存储和维护可以高效检索和操作的持久数据。例如,在社交媒体应用中,您有一个数据库,其中存储了用户数据(个人信息、帖子、评论、关注者),以一种可以高效操作的方式存储。您可以向数据库添加数据,检索数据,修改数据或删除数据,具体取决于不同的需求和条件。在网络应用中,这些需求可能包括用户添加新帖子、删除帖子或删除其账户,这可能会或可能不会删除他们的帖子。您执行的操作来操作数据将取决于应用程序中的具体功能。例如,您可能不希望用户添加没有标题的帖子。
Flask是一个轻量级的Python Web框架,为使用Python语言创建Web应用程序提供了有用的工具和功能。PostgreSQL,或者Postgres,是一个关系型数据库管理系统,提供了SQL查询语言的实现。它符合标准,并具有许多高级功能,如可靠的事务和并发性而无需读取锁定。
在本教程中,您将构建一个小型图书评论Web应用程序,演示如何使用psycopg2
库,这是一个PostgreSQL数据库适配器,允许您在Python中与PostgreSQL数据库交互。您将与Flask一起使用它来执行基本任务,如连接到数据库服务器,创建表,向表中插入数据和从表中检索数据。
先决条件
-
一个本地的Python 3编程环境。请按照如何安装和设置Python 3本地编程环境系列教程中的分发进行操作。在本教程中,项目目录称为
flask_app
。 -
对基本的Flask概念的理解,如路由、视图函数和模板。如果您对Flask不熟悉,请查看如何使用Flask和Python创建您的第一个Web应用程序和如何在Flask应用程序中使用模板。
-
对基本的HTML概念的理解。您可以查看我们的如何使用HTML构建网站教程系列来获取背景知识。
-
在您的本地计算机上安装了PostgreSQL,并且可以访问PostgreSQL提示符。按照在Ubuntu 20.04上安装和使用PostgreSQL设置您的PostgreSQL数据库。
步骤1 — 创建PostgreSQL数据库和用户
在此步骤中,您将创建一个名为flask_db
的数据库和一个名为sammy
的数据库用户,用于您的Flask应用程序。
在Postgres安装过程中,创建了一个名为postgres
的操作系统用户,对应于postgres
PostgreSQL管理用户。您需要使用此用户执行管理任务。您可以使用sudo
并使用-iu
选项传递用户名。
使用以下命令登录到交互式Postgres会话:
您将获得一个PostgreSQL提示符,您可以在其中设置您的要求。
首先,为您的项目创建一个数据库:
注意:每个Postgres语句必须以分号结束,所以如果你遇到问题,请确保你的命令以分号结束。
接下来,为我们的项目创建一个数据库用户。确保选择一个安全的密码:
然后给这个新用户访问和管理你的新数据库的权限:
要确认数据库已创建,请键入以下命令以获取数据库列表:
你将在数据库列表中看到flask_db
。
完成后,通过键入以下命令退出PostgreSQL提示符:
现在Postgres已设置完成,你可以使用psycopg2
库连接并管理其数据库信息。接下来,你将在Flask包旁边安装这个库。
步骤 2 — 安装 Flask 和 psycopg2
在这一步中,你将安装Flask和psycopg2
库,以便使用Python与数据库交互。
在激活虚拟环境的情况下,使用pip
安装Flask和psycopg2
库:
安装成功后,你将在输出的最后看到类似以下的一行:
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 psycopg2-binary-2.9.2
现在你的虚拟环境中已安装了所需的包。接下来,你将连接并设置你的数据库。
步骤 3 — 设置数据库
在这一步中,您将在您的flask_app
项目目录中创建一个 Python 文件,用于连接到flask_db
数据库,创建一个用于存储图书和评论的表,并向其中插入一些图书。
首先,确保您的编程环境已激活,然后在flask_app
目录中打开一个名为init_db.py
的新文件。
这个文件将会连接到flask_db
数据库,创建一个名为books
的表,并使用样本数据填充表格。将以下代码添加到文件中:
保存并关闭文件。
在这个文件中,首先导入os
模块,您将使用它来访问环境变量,其中您将存储数据库用户名和密码,以便它们不会在源代码中可见。
您导入psycopg2
库。然后,您使用psycopg2.connect()
函数打开到flask_db
数据库的连接。您指定了主机,这在这种情况下是本地主机。您将数据库名称传递给database
参数。
您通过os.environ
对象提供用户名和密码,该对象使您可以访问在编程环境中设置的环境变量。您将数据库用户名存储在名为DB_USERNAME
的环境变量中,将密码存储在名为DB_PASSWORD
的环境变量中。这样一来,您可以将用户名和密码存储在源代码之外,这样当源代码保存在源代码控制中或上传到互联网上的服务器时,您的敏感信息就不会泄露。即使攻击者获得了您的源代码,他们也无法访问数据库。
您使用connection.cursor()
方法创建了一个名为cur
的游标,该游标允许Python代码在数据库会话中执行PostgreSQL命令。
您使用游标的execute()
方法来删除books
表,如果它已经存在。这样可以避免另一个名为books
的表存在,这可能导致混乱的行为(例如,如果它具有不同的列)。在这里不是这种情况,因为您还没有创建表,所以SQL命令不会被执行。请注意,每当执行此init_db.py
文件时,这将删除所有现有数据。对于我们的目的,您只会执行一次此文件来初始化数据库,但您可能希望再次执行它以删除您插入的任何数据,并重新开始使用初始示例数据。
然后,您使用CREATE TABLE books
来创建一个名为books
的表,其包含以下列:
id
:serial
类型的ID,这是一个自动递增的整数。此列表示您使用PRIMARY KEY
关键字指定的主键。数据库将为每个条目分配一个唯一值。title
:varchar
类型的书名,这是一个带有限制的可变长度字符类型。varchar (150)
表示标题可以长达150个字符。NOT NULL
表示此列不能为空。author
:书的作者,限制为50个字符。NOT NULL
表示此列不能为空。pages_num
:表示书籍页数的整数。NOT NULL
表示此列不能为空。review
:书评。text
类型表示评论可以是任意长度的文本。date_added
:将书籍添加到表中的日期。DEFAULT
将列的默认值设置为CURRENT_TIMESTAMP
,即将书籍添加到数据库的时间。 就像id
一样,您不需要为此列指定值,因为它将自动填充。
创建表后,您可以使用游标的 execute()
方法将两本书插入表中,《双城记》,作者是查尔斯·狄更斯,以及 《安娜·卡列尼娜》,作者是列夫·托尔斯泰。 您使用 %s
占位符将值传递给 SQL 语句。 psycopg2
在后台处理插入,以防止 SQL 注入攻击。
完成向表中插入书籍数据后,您使用 connection.commit()
方法提交事务并将更改应用到数据库。 然后,通过使用 cur.close()
关闭游标和 conn.close()
关闭连接来清理事务。
要建立数据库连接,请通过运行以下命令设置 DB_USERNAME
和 DB_PASSWORD
环境变量。 记得使用您自己的用户名和密码:
现在,在终端中使用 python
命令运行您的 init_db.py
文件:
一旦文件执行完毕且没有错误,将会在您的flask_db
数据库中添加一个新的books
表。
登录到一个交互式的Postgres会话中,检查新的books
表。
使用\c
命令连接到flask_db
数据库:
然后使用SELECT
语句从books
表中获取书籍的标题和作者:
您将会看到如下输出:
title | author
----------------------+------------------
A Tale of Two Cities | Charles Dickens
Anna Karenina | Leo Tolstoy
使用\q
退出交互式会话。
接下来,您将创建一个小型的Flask应用程序,连接到数据库,检索您插入到数据库中的两篇书评,并在首页上显示它们。
步骤 4 — 显示书籍
在此步骤中,您将创建一个带有索引页面的Flask应用程序,该页面检索数据库中的书籍,并将它们显示出来。
在激活您的编程环境并安装了Flask后,打开名为app.py
的文件进行编辑,该文件位于您的flask_app
目录中:
此文件将设置您的数据库连接并创建一个单独的Flask路由来使用该连接。将以下代码添加到文件中:
保存并关闭文件。
在这里,您导入os
模块,psycopg2
库,以及Flask
类和flask
包中的render_template()
函数。您创建了一个名为app
的Flask应用实例。
您定义了一个名为get_db_connection()
的函数,该函数使用您在DB_USERNAME
和DB_PASSWORD
环境变量中存储的用户名和密码,打开到flask_db
数据库的连接。该函数返回conn
连接对象,您将使用它来访问数据库。
然后,您创建了一个主要的/
路由和一个index()
视图函数,使用app.route()
装饰器。在index()
视图函数中,您使用get_db_connection()
函数打开数据库连接,创建一个游标,并执行SELECT * FROM books;
SQL语句以获取数据库中的所有图书。您使用fetchall()
方法将数据保存在一个名为books
的变量中。然后关闭游标和连接。最后,您返回对render_template()
函数的调用,以渲染一个名为index.html
的模板文件,并传递从数据库中获取的书籍列表,存储在books
变量中。
要在主页上显示您数据库中的图书,首先您将创建一个基本模板,该模板将包含所有其他模板将使用的基本HTML代码,以避免代码重复。然后,您将创建您在index()
函数中呈现的index.html
模板文件。要了解有关模板的更多信息,请参阅如何在Flask应用程序中使用模板。
创建一个templates
目录,然后打开一个名为base.html
的新模板:
将以下代码添加到base.html
文件中:
保存并关闭文件。
这个基本模板包含了您在其他模板中需要重用的所有HTML样板。 title
块将被替换为为每个页面设置标题,content
块将被替换为每个页面的内容。导航栏有两个链接,一个是指向主页的链接,您在其中使用url_for()
辅助函数来链接到index()
视图函数,另一个是指向应用程序中的一个关于页面的链接(如果您选择在应用程序中包含一个的话)。
接下来,打开一个名为index.html
的模板。 这是您在app.py
文件中引用的模板:
将以下代码添加到其中:
保存并关闭文件。
在这个文件中,您扩展了基本模板,并替换了content
块的内容。您使用一个<h1>
标题,它也作为标题。
您在{% for book in books %}
这一行中使用了一个Jinja for
循环,以遍历books
列表中的每一本书。您显示了书的ID,这是使用book[0]
来获取的第一项。然后您显示了书的标题、作者、页数、评论以及添加书的日期。
当您在激活了虚拟环境的flask_app
目录中时,通过设置FLASK_APP
环境变量,告诉Flask应用程序(在这种情况下是app.py
)。然后将FLASK_ENV
环境变量设置为development
以在开发模式下运行应用程序,并获得调试器的访问权限。有关Flask调试器的更多信息,请参见如何在Flask应用程序中处理错误。使用以下命令执行此操作:
确保如果尚未设置,则设置DB_USERNAME
和DB_PASSWORD
环境变量:
接下来,运行应用程序:
在开发服务器运行时,使用浏览器访问以下URL:
http://127.0.0.1:5000/
您将在首次初始化时看到您添加到数据库的书籍。
您已经在索引页面上显示了数据库中的书籍。现在您需要允许用户添加新书。您将在下一步中为添加书籍添加一个新路由。
步骤5 — 添加新书
在这一步中,您将为向数据库添加新书和评论创建一个新路由。
您将添加一个带有 Web 表单的页面,用户在其中输入书名、作者、页数和书评。
保持开发服务器运行,并打开一个新的终端窗口。
首先,打开您的 app.py
文件:
为处理 Web 表单,您需要从 flask
包中导入一些内容:
- 全局
request
对象以访问提交的数据。 url_for()
函数以生成 URL。redirect()
函数在向数据库添加书籍后将用户重定向到索引页面。
将这些导入添加到文件的第一行:
然后在 app.py
文件末尾添加以下路由:
保存并关闭文件。
在这个路由中,您将元组 ('GET', 'POST')
传递给 methods
参数,以允许 GET 和 POST 请求。GET 请求用于从服务器检索数据。POST 请求用于向特定路由提交数据。默认情况下,只允许 GET 请求。当用户首次使用 GET 请求请求 /create
路由时,将呈现一个名为 create.html
的模板文件。稍后您将编辑此路由以处理用户填写并提交新书籍的 Web 表单的 POST 请求。
打开新的 create.html
模板:
将以下代码添加到其中:
保存并关闭文件。
您扩展了基础模板,设置了一个标题作为标题,并使用 <form>
标签,其中 method
属性设置为 post
,以指示该表单将提交 POST 请求。
您有一个名称为 title
的文本字段,您将使用它来访问您的 /create
路由中的标题数据。
您为作者设置了一个文本字段,为书籍页数设置了一个数字字段,并为书评设置了一个文本区域。
最后,您在表单末尾有一个 提交 按钮。
现在,开发服务器正在运行,请使用浏览器导航到 /create
路由:
http://127.0.0.1:5000/create
您将看到一个 添加新书籍 页面,其中包含一个用于书名的输入字段,一个用于作者的输入字段,一个用于书籍页数的输入字段,一个用于书评的文本区域,以及一个 提交 按钮。
如果您填写表单并提交它,发送一个POST请求到服务器,但什么也不会发生,因为您没有在/create
路由上处理POST请求。
打开app.py
来处理用户提交的POST请求:
编辑/create
路由如下:
保存并关闭文件。
您在if request.method == 'POST'
条件内处理POST请求。您从request.form
对象中提取标题、作者、页数和用户提交的评论。
您使用get_db_connection()
函数打开数据库,并创建一个游标。然后执行INSERT INTO
SQL语句将用户提交的标题、作者、页数和评论插入到books
表中。
您提交事务并关闭游标和连接。
最后,您将用户重定向到首页,在那里他们可以看到新添加的书籍在现有书籍下方。
在开发服务器运行时,使用浏览器导航到/create
路由:
http://127.0.0.1:5000/create
填写表单并提交。
您将被重定向到首页,您将在那里看到您的新书评论。
接下来,您将在导航栏中添加一个链接到创建页面。打开base.html
:
编辑文件如下:
保存并关闭文件。
在导航栏中添加一个指向创建页面的新链接
刷新您的首页,您将在导航栏中看到新链接。
现在您有一个包含网页表单的页面,用于添加新的书评。有关网页表单的更多信息,请参阅如何在Flask应用程序中使用Web表单。对于管理网页表单的更高级和更安全的方法,请参阅如何使用Flask-WTF验证Web表单。
结论
您已经为书评构建了一个与PostgreSQL数据库通信的小型Web应用程序。您的Flask应用程序具有基本的数据库功能,例如向数据库添加新数据,检索数据并在页面上显示它。
如果您想阅读更多关于Flask的信息,请查看Flask系列中的其他教程。