如何在 Flask 应用程序中使用 SQLite 数据库

作者选择了 自由和开源基金作为 写给捐款计划的一部分接受捐款。

介绍

在 Web 应用程序中,你通常需要一个 database,这是一个有组织的数据收集。你使用数据库来存储和维护可有效地检索和操纵的持久数据。例如,在社交媒体应用程序中,你有一个用户数据库(个人信息,帖子,评论,追随者)以一种可以有效地操纵的方式存储。你可以将数据添加到数据库,获取它,修改它或删除它,取决于不同的要求和条件。在 Web 应用程序中,这些要求可能是用户添加新帖子,删除帖子或删除他们的帐户,这可能会或可能不会删除他们的帖子。你执行的操作来操纵数据将取决于应用程序中的特定功能。例如,你可能不想让用户添加没有标题的帖子。

Flask是一个轻量级的Python网页框架,为在Python语言中创建网页应用程序提供了有用的工具和功能。 SQLite是一个简单而快速的开源SQL引擎(https://en.wikipedia.org/wiki/Database_engine)可与Python一起使用来存储和操纵应用数据。

在本教程中,您将构建一个小型Web应用程序,展示如何使用SQLite与Flask进行基本数据操纵,涵盖CRUD:创建,阅读,更新和删除。

前提条件

在本教程中,我们将把我们的项目目录称为flask_app

步骤 1 - 创建数据库

在此步骤中,您将设置用于存储数据的 SQLite 数据库(应用程序的博客帖子)。

您将使用 sqlite3模块与数据库进行交互,该数据库在标准的Python库中可用。

SQLite 中的数据存储在表和列中,所以您首先需要创建一个名为帖子的表,其中包含所需的列.您将创建一个包含 SQL 命令的.sql 文件,以创建几个列的帖子表。

在您的flask_app目录中打开名为schema.sql的数据库架构文件:

1nano schema.sql

在此文件中输入以下 SQL 命令:

1[label flask_app/schema.sql]
2DROP TABLE IF EXISTS posts;
3
4CREATE TABLE posts (
5    id INTEGER PRIMARY KEY AUTOINCREMENT,
6    created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
7    title TEXT NOT NULL,
8    content TEXT NOT NULL
9);

保存并关闭文件。

在此方案文件中,您首先删除帖子表,如果它已经存在,这将避免另一个名为帖子的表存在的可能性,这可能会导致混淆的行为(例如,如果它有不同的列)。 在这里,这并非如此,因为您尚未创建表,所以SQL命令不会执行。 请注意,这将删除所有现有数据,每次您执行该方案文件。 对于我们的目的,您只会执行此方案一次,但您可能想再次执行它以删除您插入的任何数据,并重新开始使用一个空的数据库。

接下来,您使用CREATE TABLE posts创建posts表,其中包含以下列:

  • id: 代表一个 primary key 的整数. 此密钥将由数据库为每个条目(即每个博客帖)分配一个独特的值。 AUTOINCREMENT 会自动增加帖子ID,因此第一个帖子将具有 1 的 ID,然后添加的帖子将具有 2 的 ID,等等。 每个帖子将始终具有相同的 ID,即使其他帖子被删除
  • created: 博客帖创建的时间. NOT NULL 意味着这个列不应该空,而 DEFAULT 值意味着 CURRENT_TIMESTAMP 值,即该帖子被添加到数据库的时刻。

现在,你将使用schema.sql文件来创建数据库. 要做到这一点,你将创建一个 Python 文件,它将基于这个schema.sql文件生成一个 SQLite .db’ 数据库文件。 在你的flask_app目录中打开一个名为init_db.py`的文件:

1nano init_db.py

添加以下代码:

 1[label flask_app/init_db.py]
 2import sqlite3
 3
 4connection = sqlite3.connect('database.db')
 5
 6with open('schema.sql') as f:
 7    connection.executescript(f.read())
 8
 9cur = connection.cursor()
10
11cur.execute("INSERT INTO posts (title, content) VALUES (?, ?)",
12            ('First Post', 'Content for the first post')
13            )
14
15cur.execute("INSERT INTO posts (title, content) VALUES (?, ?)",
16            ('Second Post', 'Content for the second post')
17            )
18
19connection.commit()
20connection.close()

你首先导入sqlite3模块,你打开一个连接到一个名为database.db的数据库文件,这将创建在你运行Python文件后。然后你使用open()函数来打开schema.sql文件。接下来,你使用executescript()(https://docs.python.org/3/library/sqlite3.html#sqlite3.Connection.executescript)方法执行其内容,同时执行多个SQL陈述,这将创建帖子表。你创建一个Cursor object(https://docs.python.org/3/library/sqlite3.html#cursor-objects)函数,允许你在数据库中处理行。在这种情况下,你将使用指示器的execute()(https://docs.python.org/3/library/sqlite3.html#sqlite3.Cursor.execute)方法执行两个INSERTSQL陈述,将两个博客帖添加到你的帖子表中。最后,你执行更改和关闭连

保存和关闭文件,然后使用python命令在终端运行它:

1python init_db.py

一旦该文件完成执行,一个名为 database.db的新文件将出现在您的 flask_app 目录中,这意味着您已经成功设置了您的数据库。

接下来,您将创建一个小型的Flask应用程序,获取您插入数据库的两个帖子,并在索引页面上显示它们。

步骤2 - 显示帖子

在此步骤中,您将创建一个Flask应用程序,具有索引页面,显示您在数据库中的博客帖子。

当您的编程环境启用并安装Flask时,请打开名为app.py的文件,在您的flask_app目录中进行编辑:

1nano app.py

此文件将设置您的数据库连接,并创建一个单一的 Flask 路径来使用该连接。

 1[label flask_app/app.py]
 2import sqlite3
 3from flask import Flask, render_template
 4
 5app = Flask(__name__)
 6
 7def get_db_connection():
 8    conn = sqlite3.connect('database.db')
 9    conn.row_factory = sqlite3.Row
10    return conn
11
12@app.route('/')
13def index():
14    conn = get_db_connection()
15    posts = conn.execute('SELECT * FROM posts').fetchall()
16    conn.close()
17    return render_template('index.html', posts=posts)

保存并关闭文件。

在上面的代码中,你首先导入sqlite3模块来使用它来连接到你的数据库,然后你从flask包中导入Flask类和render_template()函数。你创建了一个名为app的Flask应用程序实例。你定义了一个名为get_db_connection()的函数,该函数打开了一个连接到你之前创建的database.db数据库文件,并将row_factory(https://docs.python.org/3/library/sqlite3.html#sqlite3.Connection.row_factory)属性设置为sqlite3.Row,这样你就可以以名义访问列。这意味着数据库连接会返回行为像常规的Python字典的行。最后,该函数返回你将使用的conn连接对

然后使用app.route()装饰程序创建一个名为index()Flask 视图函数。 您使用get_db_connection()函数打开数据库连接,然后运行 SQL 查询,从帖子表中选择所有条目。 您使用fetchall()方法(https://docs.python.org/3/library/sqlite3.html#sqlite3.Cursor.fetchall)获取查询结果的所有行,这将返回您在上一步中插入数据库的帖子列表。

您使用 close()方法关闭数据库连接并返回index.html模板的渲染结果. 您还将帖子对象作为一个参数传递,其中包含您从数据库中获得的结果。

要在索引页面上显示您在数据库中的帖子,您首先将创建一个基础模板,该模板将具有其他模板也将使用的所有基本HTML代码,以避免代码重复。

创建一个模板目录,然后打开一个名为base.html的新模板:

1mkdir templates
2nano templates/base.html

将以下代码添加到base.html文件中:

 1[label flask_app/templates/base.html]
 2<!DOCTYPE html>
 3<html lang="en">
 4<head>
 5    <meta charset="UTF-8">
 6    <title>{% block title %} {% endblock %}- FlaskApp</title>
 7    <style>
 8        .post {
 9            padding: 10px;
10            margin: 5px;
11            background-color: #f3f3f3
12        }
13
14        nav a {
15            color: #d64161;
16            font-size: 3em;
17            margin-left: 50px;
18            text-decoration: none;
19        }
20    </style>
21</head>
22<body>
23    <nav>
24        <a href="{{ url_for('index') }}">FlaskApp</a>
25        <a href="#">About</a>
26    </nav>
27    <hr>
28    <div class="content">
29        {% block content %} {% endblock %}
30    </div>
31</body>
32</html>

保存并关闭文件。

此基础模板包含您在其他模板中需要重复使用的所有HTML锅炉板。标题块将被更换为为每个页面设置一个标题,而内容块将被替换为每个页面的内容。导航栏有两个链接,一个用于索引页面,其中您使用url_for()辅助函数链接到index()视图函数,另一个用于关于页面,如果您选择在应用程序中包含一个链接。

接下来,打开一个名为index.html的模板,这是你在app.py文件中提到的模板:

1nano templates/index.html

添加以下代码:

 1[label flask_app/templates/index.html]
 2{% extends 'base.html' %}
 3
 4{% block content %}
 5    <h1>{% block title %} Posts {% endblock %}</h1>
 6    {% for post in posts %}
 7        <div class='post'>
 8            <p>{{ post['created'] }}</p>
 9            <h2>{{ post['title'] }}</h2>
10            <p>{{ post['content'] }}</p>
11        </div>
12    {% endfor %}
13{% endblock %}

保存并关闭文件。

在上面的代码中,你扩展了base.html模板并取代了内容块的内容,你使用一个<h1>标题,它也作为一个标题。

你在字符串中使用一个 Jinja for loop 来浏览帖子列表中的每个帖子,你可以通过创建日期访问创建的帖子,通过创建的帖子的标题,通过创建的帖子的内容。

在您的flask_app目录中,您的虚拟环境已启用,请使用FLASK_APP环境变量告诉Flask关于该应用程序(在这种情况下,app.py):

1export FLASK_APP=app

然后将FLASK_ENV环境变量设置为development,以便在开发模式下运行应用程序并获取调试器的访问。 有关 Flask 调试器的更多信息,请参阅 如何处理 Flask 应用程序中的错误

1export FLASK_ENV=development

接下来,运行应用程序:

1flask run

当开发服务器运行时,请使用您的浏览器访问以下URL:

1http://127.0.0.1:5000/

您将看到您在第一个启动时添加到数据库的帖子。

Index Page

您已在索引页面上显示了数据库中的帖子. 您现在需要允许用户添加新帖子. 您将在下一步添加新路线来添加帖子。

步骤三:创建帖子

在此步骤中,您将为您的 Flask 应用程序添加一个新路线,允许用户将新博客帖子添加到数据库中,然后在索引页面上显示。

您将添加一个包含网页表单的页面,用户将输入帖子标题和发布内容。 此表单将被验证,以确保用户不提交空格表单. 为了通知用户表单是无效的,您将使用一个 flash message,它只会显示一次,并在下一个请求时消失(例如,如果您导航到另一个页面)。

让开发服务器运行,并打开一个新的终端窗口。

首先,打开app.py文件:

1nano app.py

要处理网页表格,您需要从包中导入几件东西:

  • 全球 request对象访问提交的数据
  • url_for()函数生成 URL
  • flash()函数闪烁消息,如果请求是无效的
  • redirect()函数将用户重定向到索引页面后添加到数据库的帖子

将这些导入添加到文件中的第一行:

1[label flask_app/app.py]
2from flask import Flask, render_template, request, url_for, flash, redirect
3
4# ...

闪存()函数在客户端浏览器会话中存储闪存消息,这需要设置一个 secret key 以确保会话能够记住从一个请求到另一个请求的信息。

通过app.config对象将SECRET_KEY配置添加到您的应用程序中,设置一个 _secret key。

1[label flask_app/app.py]
2
3# ...
4app = Flask(__name__)
5app.config['SECRET_KEY'] = 'your secret key'

请记住,秘密密密钥应该是一个长的随机字符串. 有关 Web 表单和秘密密密钥配置的更多信息,请参阅 如何在 Flask 应用程序中使用 Web 表单

接下来,在app.py文件的末尾添加以下路线:

1[label flask_app/app.py]
2# ...
3
4@app.route('/create/', methods=('GET', 'POST'))
5def create():
6    return render_template('create.html')

保存并关闭文件。

在此路径中,您将‘GET’,‘POST’字符串传输到‘methods’参数,以允许 GET 和 POST 请求。 GET 请求用于从服务器中获取数据。 POST 请求用于将数据发送到特定路径。默认情况下,仅允许 GET 请求。当用户使用 GET 请求首次请求‘/create’ 路径时,将生成一个名为 ‘create.html’ 的模板文件。之后,您将编辑此路径以处理用户填写和提交 Web 表格创建新帖子的 POST 请求。

打开新的create.html模板:

1nano templates/create.html

添加以下代码:

 1[label flask_app/templates/create.html]
 2{% extends 'base.html' %}
 3
 4{% block content %}
 5    <h1>{% block title %} Add a New Post {% endblock %}</h1>
 6    <form method="post">
 7        <label for="title">Title</label>
 8        <br>
 9        <input type="text" name="title"
10               placeholder="Post title"
11               value="{{ request.form['title'] }}"></input>
12        <br>
13
14        <label for="content">Post Content</label>
15        <br>
16        <textarea name="content"
17                  placeholder="Post content"
18                  rows="15"
19                  cols="60"
20                  >{{ request.form['content'] }}</textarea>
21        <br>
22        <button type="submit">Submit</button>
23    </form>
24{% endblock %}

保存并关闭文件。

您将基础模板扩展,将标题设置为标题,并使用具有方法属性设置为发布<form>标签,以表示该表单将提交POST请求。

在标题输入字段后,添加一个名为内容的文本区域,其值为{{ request.form['content'] }},以恢复表单无效的帖子内容。

最后,您在表单的末尾有一个提交按钮。

现在,随着开发服务器运行,使用您的浏览器导航到‘/create’路径:

1http://127.0.0.1:5000/create

您将看到一个 ** 添加新帖子 ** 页面,其中包含帖子标题的输入字段,帖子内容的文本区域和一个 ** 提交 ** 按钮。

Add New Post

如果您填写表单并提交它,将 POST 请求发送到服务器,则不会发生任何事情,因为您没有在/create路径上处理 POST 请求。

打开 app.py 来处理用户提交的 POST 请求:

1nano app.py

编辑/create路径以显示如下:

 1[label flask_app/app.py]
 2# ...
 3
 4@app.route('/create/', methods=('GET', 'POST'))
 5def create():
 6    if request.method == 'POST':
 7        title = request.form['title']
 8        content = request.form['content']
 9
10        if not title:
11            flash('Title is required!')
12        elif not content:
13            flash('Content is required!')
14        else:
15            conn = get_db_connection()
16            conn.execute('INSERT INTO posts (title, content) VALUES (?, ?)',
17                         (title, content))
18            conn.commit()
19            conn.close()
20            return redirect(url_for('index'))
21
22    return render_template('create.html')

保存并关闭文件。

您处理if request.method ==POST条件内的 POST 请求,您从request.form对象中提取用户提交的标题和内容,如果标题是空的,则使用flash()函数闪烁Title is required!`消息。

如果提交了标题和内容,你会使用get_db_connection()函数打开数据库连接。你会使用execute()方法执行一个INSERT INTO SQL 语句,将一个新的帖子添加到帖子表中,用户提交的标题和内容作为值。你会使用?位置持有器将数据安全地插入表中。你会发起交易并关闭连接。最后,你会将用户重定向到索引页面,在那里他们可以看到现有帖子的下方的新帖子。

<$>[warning] 警告: 永远不要使用 Python 字符串操作来动态创建 SQL 语句字符串。 始终在您的 SQL 语句中使用 ? 位数保持器来动态替代值。 将值作为第二个参数传递到 execute() 方法中,以便将值与 SQL 语句结合起来。 这会防止 SQL 注入攻击

当开发服务器运行时,使用您的浏览器导航到‘/create’路径:

1http://127.0.0.1:5000/create

填写表格并提交它。

你将被重定向到索引页面,在那里你会看到你的新帖子。

如果您提交一个没有标题或没有内容的表单,您的帖子将不会被添加到数据库中,您将不会被重定向到索引页面,并且您不会收到任何反馈,因为您尚未设置闪存消息显示在任何地方。

打开base.html,在导航栏中添加链接到创建页面,并在其下方显示闪存消息。

1nano templates/base.html

编辑文件以显示如下:

 1[label flask_app/templates/base.html]
 2<!DOCTYPE html>
 3<html lang="en">
 4<head>
 5    <meta charset="UTF-8">
 6    <title>{% block title %} {% endblock %} - FlaskApp</title>
 7    <style>
 8        .post {
 9            padding: 10px;
10            margin: 5px;
11            background-color: #f3f3f3
12        }
13
14        nav a {
15            color: #d64161;
16            font-size: 3em;
17            margin-left: 50px;
18            text-decoration: none;
19        }
20
21        .alert {
22            padding: 20px;
23            margin: 5px;
24            color: #970020;
25            background-color: #ffd5de;
26        }
27    </style>
28</head>
29<body>
30    <nav>
31        <a href="{{ url_for('index') }}">FlaskApp</a>
32        <a href="{{ url_for('create') }}">Create</a>
33        <a href="#">About</a>
34    </nav>
35    <hr>
36    <div class="content">
37        {% for message in get_flashed_messages() %}
38            <div class="alert">{{ message }}</div>
39        {% endfor %}
40
41        {% block content %} {% endblock %}
42    </div>
43</body>
44</html>

保存并关闭文件。

在这里,您将新的<a>链接添加到指向创建页面的导航栏。

您使用一个 Jinja for 循环来通过闪烁的消息,这些信息可在 get_flashed_messages() 特殊功能中使用。每个消息都显示在一个 div> 标签中,有一个名为 alert 的 CSS 类别。

更新您的索引页面,您将在导航栏中看到新的链接。

点击创建链接,然后提交一个空格表单,您将收到闪烁的消息标题是必要的!

填写标题字段,并将内容文本空白。 再次提交表单,您将收到需要内容!消息。 注意需要标题!消息是如何消失的。

接下来,您将添加一个新的路径,允许用户编辑现有帖子。

步骤4:编辑文章

在此步骤中,您将向应用程序添加一个新路径,以允许用户编辑现有帖子。

首先,要避免代码重复并隔离代码,并使其更容易维护,您将添加一个新函数,该函数需要一个ID并从数据库中获取相关的帖子。

打开app.py:

1nano app.py

您要使用的函数来获取帖子将以404 Not Found错误响应,如果所请求的帖子的 ID 与任何现有帖子不匹配. 要做到这一点,您将使用 abort()]函数,该函数会取消请求并以错误消息响应。

将 abort() 函数添加到导入中:

1[label flask_app/app.py]
2from flask import Flask, render_template, request, url_for, flash, redirect, abort

在您的get_db_connection()函数下方添加一个名为get_post()的新函数:

 1[label flask_app/app.py]
 2
 3# ...
 4
 5def get_db_connection():
 6    conn = sqlite3.connect('database.db')
 7    conn.row_factory = sqlite3.Row
 8    return conn
 9
10def get_post(post_id):
11    conn = get_db_connection()
12    post = conn.execute('SELECT * FROM posts WHERE id = ?',
13                        (post_id,)).fetchone()
14    conn.close()
15    if post is None:
16        abort(404)
17    return post
18
19# ...

这个新函数有一个post_id参数,决定要检索和返回哪个邮件. 您使用get_db_connection()打开数据库连接并执行 SQL 查询以获取与给定的post_id值相关的邮件. 您使用fetchone()方法获得邮件,将其存储在post变量中,然后关闭连接。

如果post变量具有None值,这意味着数据库中没有找到结果,则使用您先前导入的abort()函数以使用404错误代码响应,并且该函数将完成执行。

接下来,在文件末尾添加一个新路径来编辑帖子:

 1[label flask_app/app.py]
 2# ...
 3
 4@app.route('/<int:id>/edit/', methods=('GET', 'POST'))
 5def edit(id):
 6    post = get_post(id)
 7
 8    if request.method == 'POST':
 9        title = request.form['title']
10        content = request.form['content']
11
12        if not title:
13            flash('Title is required!')
14
15        elif not content:
16            flash('Content is required!')
17
18        else:
19            conn = get_db_connection()
20            conn.execute('UPDATE posts SET title = ?, content = ?'
21                         ' WHERE id = ?',
22                         (title, content, id))
23            conn.commit()
24            conn.close()
25            return redirect(url_for('index'))
26
27    return render_template('edit.html', post=post)

保存并关闭文件。

您使用路线 /<int:id>/edit/,而 int: 是一个接受正整数的 转换器的 URL 变量,该 URL 将决定您要编辑的帖子。例如, /2/edit/ 将允许您用 2’ 的 ID 编辑帖子。 ID 将从 URL 传输到 edit()’ 视图函数。 您将 id 参数’ 的值传输到 get_post() 函数以从数据库中获取与所提供的 ID 相关的帖子。 请记住,如果没有与所提供的 ID 相关的帖子,则将出现 `404 Not Found' 错误。

最后一行渲染了一个名为edit.html的模板文件,并通过具有帖子数据的帖子变量,您将使用此功能在编辑页面上显示现有的标题和内容。

「if request.method == 'POST'」块处理了用户提交的新数据。类似于添加新帖子,你提取了标题和内容。

如果表单有效,则打开数据库连接,并使用更新 SQL 语句更新帖子表,设置新的标题和新内容,其中数据库中的帖子的 ID 等于 URL 中的 ID。

接下来,您需要创建一个用户可以编辑的页面,打开一个新的edit.html 模板:

1nano templates/edit.html

添加以下代码:

 1[label flask_app/templates/edit.html]
 2{% extends 'base.html' %}
 3
 4{% block content %}
 5    <h1>{% block title %} Edit "{{ post['title'] }}" {% endblock %}</h1>
 6    <form method="post">
 7        <label for="title">Title</label>
 8        <br>
 9        <input type="text" name="title"
10               placeholder="Post title"
11               value="{{ request.form['title'] or post['title'] }}"></input>
12        <br>
13
14        <label for="content">Post Content</label>
15        <br>
16        <textarea name="content"
17                  placeholder="Post content"
18                  rows="15"
19                  cols="60"
20                  >{{ request.form['content'] or post['content'] }}</textarea>
21        <br>
22        <button type="submit">Submit</button>
23    </form>
24{% endblock %}

保存并关闭文件。

这是类似于create.html模板中的代码,除了在{% block title %}字段中显示页面标题中的帖子标题外,{{post['title'] }} {% endblock %}的编辑,在{{ request.form['title'] 或 post['title'] }}的输入值,以及在`{{ request.form['content']]或 post['content'] }}的文本区域的值。

当开发服务器运行时,使用您的浏览器导航到以下URL来编辑第一个帖子:

1http://127.0.0.1:5000/1/edit

你会看到一个看起来如下的一页:

Edit Post

编辑帖子并提交表单. 您将看到您的更改应用于索引页面. 如果您提交表单没有标题或没有任何内容,您将收到闪烁的消息。

现在您需要添加一个链接,指向索引页面的每个帖子的编辑页面。

1nano templates/index.html

编辑文件以完全看起来如下:

 1[label flask_app/templates/index.html]
 2
 3{% extends 'base.html' %}
 4
 5{% block content %}
 6    <h1>{% block title %} Posts {% endblock %}</h1>
 7    {% for post in posts %}
 8        <div class='post'>
 9            <p>{{ post['created'] }}</p>
10            <h2>{{ post['title'] }}</h2>
11            <p>{{ post['content'] }}</p>
12            <a href="{{ url_for('edit', id=post['id']) }}">Edit</a>
13        </div>
14    {% endfor %}
15{% endblock %}

保存并关闭文件。

您添加了链接到edit()视图函数的<a>标签,您将您在post['id'])中所拥有的邮件ID传递到url_for()函数,以生成邮件的编辑链接。

更新索引页面,然后点击编辑链接来编辑帖子。

您现在可以添加新的帖子并编辑现有的帖子,接下来,您将添加一个按钮,允许用户删除现有的帖子。

步骤5:删除帖子

在此步骤中,您将添加删除按钮到编辑页面,以允许用户删除帖子。

首先,您将添加一个新的/id/delete路径,该路径接受POST请求,类似于edit()视图函数。您的新delete()视图函数将收到从URL中删除的帖子的ID,使用get_post()函数获取它,然后从数据库中删除它,如果它存在的话。

打开app.py文件:

1nano app.py

把下列路线添加到结尾:

 1[label flask_app/app.py]
 2# ...
 3
 4@app.route('/<int:id>/delete/', methods=('POST',))
 5def delete(id):
 6    post = get_post(id)
 7    conn = get_db_connection()
 8    conn.execute('DELETE FROM posts WHERE id = ?', (id,))
 9    conn.commit()
10    conn.close()
11    flash('"{}" was successfully deleted!'.format(post['title']))
12    return redirect(url_for('index'))

保存并关闭文件。

此视图功能只接受方法参数中的 POST 请求,这意味着导航到浏览器上的ID/删除路径会返回405 方法不允许错误,因为 Web 浏览器默认的 GET 请求。

该函数接收要删除的帖子的 ID. 您使用此 ID 以使用 get_post() 函数获取帖子. 此函数以 404 Not Found 错误响应,如果没有包含给定的 ID 的帖子。 您打开数据库连接并执行一个 DELETE FROM SQL 命令来删除帖子. 您使用 WHERE id =? 指定要删除的帖子。

您将对数据库进行更改,并关闭连接. 您会闪烁一个消息,通知用户该帖子已成功删除,并将其重定向到索引页面。

请注意,您不会渲染模板文件,因为您只会将删除按钮添加到编辑页面。

打开edit.html模板文件:

1nano templates/edit.html

然后在{% endblock %}行前直接添加以下<hr><form>标签:

 1[label flask_app/templates/edit.html]
 2        <button type="submit">Submit</button>
 3    </form>
 4
 5    <hr>
 6    <form action="{{ url_for('delete', id=post['id']) }}" method="POST">
 7        <input type="submit" value="Delete Post"
 8                onclick="return confirm('Are you sure you want to delete this post?')">
 9    </form>
10{% endblock %}

保存并关闭文件。

在这里,你有一个网页表格,将POST请求提交到删除()视图函数中。你通过post['id']来指定要删除的帖子。你使用在网页浏览器中可用的confirm()方法,在提交请求之前显示确认消息。

现在再次导航到一篇文章的编辑页面,并尝试删除它:

1http://127.0.0.1:5000/1/edit

确认删除后,您将被重定向到索引页面,该帖子将不再存在,导航栏下方会出现闪存消息,通知您该帖子已成功删除。

现在你有办法从Flask应用程序中的数据库中删除不需要的帖子。

结论

您建立了一個與 SQLite 資料庫溝通的小型網頁,在您的 Flask 應用程式中有基本功能,例如將新資料添加到資料庫中,搜尋資料並在頁面上顯示,以及編輯和刪除現有資料。

有关如何使用SQLite与Python和Flask的更多信息,请参阅以下教程:

如果您想了解更多关于Flask的信息,请查看Flask系列中的其他教程(https://www.digitalocean.com/community/tutorial_series/how-to-create-web-sites-with-flask)。

Published At
Categories with 技术
comments powered by Disqus