作者选择了 COVID-19 救援基金作为 Write for Donations计划的一部分接受捐款。
介绍
Flask是使用 Python 语言构建 Web 应用程序的框架,使用 Flask,您可以使用 SQLite作为您的数据库引擎来存储应用程序数据。
Markdown是一个标记语言,通常用于在易于阅读的文本格式中写内容的过程。使用Markdown,您可以用标题,链接和图像等功能格式化简单文本,然后可以将文本转换为HTML,其中包括这些格式化功能。
Python-Markdown是一个Python库,允许您将Markdown文本转换为HTML;它大多遵循Markdown标准,与标准Markdown语法有少数差异(https://python-markdown.github.io/#differences)。
在本教程中,您将使用Flask,SQLite和Python-Markdown来构建一个小型备注的Web应用程序,该应用程序将允许用户显示,创建和格式化标题,链接,列表,图像和其他功能。
前提条件
- 一个本地的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_notes. - 对基本的Flask概念的理解,如创建路线,渲染HTML模板,并连接到SQLite数据库。 检查一下如何使用Python 3中的Flask Web应用程序(https://andsky.com/tech/tutorials/how-to-make-a-web-application-using-flask-in-python-3)和如何使用Python 3中的Sqlite3模块(https://andsky.com/tech/tutorials/how-to-use-the-sqlite3-module-in-python-3),如果你不熟悉这些概念。
步骤一:建立依赖性
在此步骤中,您将激活您的 Python 环境并使用 pip 包安装程序安装 Flask 和 Python-Markdown. 然后您将创建您将使用的数据库来存储笔记并添加一些样本数据。
首先,如果您尚未启用您的编程环境:
1source env/bin/activate
一旦激活了编程环境,请使用以下命令安装Flask和Python-Markdown库:
1pip install flask markdown
然后创建一个名为schema.sql的数据库架构文件,其中包含 SQL 命令来创建一个笔记表。
1nano schema.sql
在此文件中输入以下 SQL 命令:
1[label flask_notes/schema.sql]
2DROP TABLE IF EXISTS notes;
3
4CREATE TABLE notes (
5 id INTEGER PRIMARY KEY AUTOINCREMENT,
6 created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
7 content TEXT NOT NULL
8);
在此 SQL 文件中,您首先删除任何已存在的表名为笔记,这可能会导致问题。这确保您的笔记表完全如本 SQL 中所述。
您可以使用「CREATE TABLE NOTES」语句来创建包含以下列的「Notes」表:
id:代表一个 primary key 的整数;数据库将为每个输入(注释)分配一个独特的值。created: 注释的创建日期;它将自动填写注释被添加到数据库的时间。
保存并关闭文件。
若要使用schema.sql文件创建数据库,请在flask_notes目录中打开名为init_db.py的文件:
1nano init_db.py
然后添加以下代码:
1[label flask_notes/init_db.py]
2
3import sqlite3
4
5connection = sqlite3.connect('database.db')
6
7with open('schema.sql') as f:
8 connection.executescript(f.read())
9
10cur = connection.cursor()
11
12cur.execute("INSERT INTO notes (content) VALUES (?)", ('# The First Note',))
13cur.execute("INSERT INTO notes (content) VALUES (?)", ('_Another note_',))
14cur.execute("INSERT INTO notes (content) VALUES (?)", ('Visit [this page](https://andsky.com/tech/tutorials) for more tutorials.',))
15
16connection.commit()
17connection.close()
在这里,您首先导入sqlite3模块,然后连接到一个名为database.db的文件,该文件将在运行该程序后创建。database.db是存储所有应用程序数据的数据库,然后打开schema.sql文件并使用executescript()(https://docs.python.org/3/library/sqlite3.html#sqlite3.Connection.executescript)方法运行它,同时执行多个SQL陈述。
使用 Cursor 对象,您执行几个INSERT SQL 语句来创建三个笔记. 您在这里使用 Markdown 语法:第一个笔记是<h1>标题,第二个笔记是意大利语,第三个笔记包含链接. 您在 execute()方法中使用`?
最后,您执行更改并关闭连接。
保存并关闭文件。
运行这个程序:
1python init_db.py
執行後,一個名為「database.db」的新檔案會出現在您的「flask_notes」目錄中。
您已激活您的环境,安装了 Flask 和 Python-Markdown,并创建了 SQLite 数据库。接下来,您将从数据库中获取 Markdown 笔记,将其转换为 HTML,并在应用程序的主页上显示。
步骤 2 – 在索引页面上显示笔记
在此步骤中,您将创建一个Flask应用程序,连接到数据库并显示您在数据库中所拥有的样本数据,然后将数据库中的Markdown文本转换为HTML,然后在索引页面上渲染。
首先,在您的flask_notes目录中创建app.py应用程序文件:
1nano app.py
添加以下代码:
1[label flask_notes/app.py]
2import sqlite3
3import markdown
4from flask import Flask, render_template, request, flash, redirect, url_for
5
6def get_db_connection():
7 conn = sqlite3.connect('database.db')
8 conn.row_factory = sqlite3.Row
9 return conn
您首先导入sqlite3模块、标记包和Flask 助手。
「get_db_connection()」函数打开了连接到「database.db」数据库文件,然后将 row_factory属性设置为「sqlite3.Row」。 这为您提供了基于名称的访问列,这意味着数据库连接会返回行为像常规Python字典的行。
接下来,添加下一个代码片段:
1[label flask_notes/app.py]
2#. . .
3
4app = Flask(__name__)
5app.config['SECRET_KEY'] = 'this should be a secret random string'
在这里,您创建了 Flask 应用程序对象,并将秘密密密钥设置为 安全会话。
然后添加以下代码:
1[label flask_notes/app.py]
2#. . .
3
4@app.route('/')
5def index():
6 conn = get_db_connection()
7 db_notes = conn.execute('SELECT id, created, content FROM notes;').fetchall()
8 conn.close()
9
10 notes = []
11 for note in db_notes:
12 note = dict(note)
13 note['content'] = markdown.markdown(note['content'])
14 notes.append(note)
15
16 return render_template('index.html', notes=notes)
该 index() 函数是 Flask view function,这是使用特殊 @app.route decorator装饰的函数。
在index()视图函数中,您打开数据库连接并执行一个SELECT SQL 语句,以获取notes表的所有行ID、创建日期和内容。
要将笔记内容从 Markdown 转换为 HTML,你会创建一个名为notes的新空列表。你会穿过db_notes列表并将每个笔记从sqlite3.Row转换为常规的 Python 字典,使用dict() Python 函数来允许分配。接下来,你会使用markdown.markdown()函数将note['content]的值转换为 HTML。例如,调用markdown.markdown('#Hi')会返回字符串<h1>Hi</h1>,因为在markdown中#代表<h1>标题。修改note['content]后,你会将笔记附加到notes列表中。
最后,您会渲染一个名为index.html的模板文件,将其传递到注释列表中。
在所有添加后,您的文件将如下:
1[label flask_notes/app.py]
2import sqlite3
3import markdown
4from flask import Flask, render_template, request, flash, redirect, url_for
5
6def get_db_connection():
7 conn = sqlite3.connect('database.db')
8 conn.row_factory = sqlite3.Row
9 return conn
10
11app = Flask(__name__)
12app.config['SECRET_KEY'] = 'this should be a secret random string'
13
14@app.route('/')
15def index():
16 conn = get_db_connection()
17 db_notes = conn.execute('SELECT id, created, content FROM notes;').fetchall()
18 conn.close()
19
20 notes = []
21 for note in db_notes:
22 note = dict(note)
23 note['content'] = markdown.markdown(note['content'])
24 notes.append(note)
25
26 return render_template('index.html', notes=notes)
保存并关闭文件。
接下来,您将创建一个基础模板和index.html模板文件。
在您的flask_notes目录中,创建一个模板目录,并在其内部打开一个名为base.html的文件:
1mkdir templates
2nano templates/base.html
如果你不熟悉Flask中的HTML模板,请阅读How To Make A Web Application Using Flask in Python 3(LINK1):
1[label flask_notes/templates/base.html]
2<!doctype html>
3<html lang="en">
4 <head>
5 <!-- Required meta tags -->
6 <meta charset="utf-8">
7 <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
8
9 <!-- Bootstrap CSS -->
10 <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
11
12 <title>{% block title %} {% endblock %}</title>
13 </head>
14 <body>
15 <nav class="navbar navbar-expand-md navbar-light bg-light">
16 <a class="navbar-brand" href="{{ url_for('index')}}">FlaskNotes</a>
17 <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
18 <span class="navbar-toggler-icon"></span>
19 </button>
20 <div class="collapse navbar-collapse" id="navbarNav">
21 <ul class="navbar-nav">
22 <li class="nav-item active">
23 <a class="nav-link" href="#">About</a>
24 </li>
25 </ul>
26 </div>
27 </nav>
28 <div class="container">
29 {% for message in get_flashed_messages() %}
30 <div class="alert alert-danger">{{ message }}</div>
31 {% endfor %}
32 {% block content %} {% endblock %}
33 </div>
34
35 <!-- Optional JavaScript -->
36 <!-- jQuery first, then Popper.js, then Bootstrap JS -->
37 <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
38 <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
39 <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
40 </body>
41</html>
上一块的大部分代码是标准的HTML和Bootstrap所需的代码. 网页浏览器的<meta>标签提供信息, Bootstrap CSS 文件的<link>标签链接,而<script>标签是 JavaScript 代码的链接,允许一些额外的 Bootstrap 功能。
标签 <title>{% block title %} {% endblock %}</title> 允许继承模板定义自定义标题. 您可以使用 for message in get_flashed_messages() 循环显示闪存消息,如警告和警告。
保存并关闭文件。
接下来,创建将这个base.html文件扩展的index.html文件:
1nano templates/index.html
添加以下代码:
1[label flask_notes/templates/index.html]
2
3{% extends 'base.html' %}
4
5{% block content %}
6 <h1>{% block title %} Welcome to FlaskNotes {% endblock %}</h1>
7 {% for note in notes %}
8 <div class="card">
9 <div class="card-body">
10 <span class="badge badge-primary">#{{ note['id'] }}</span>
11 <span class="badge badge-default">{{ note['created'] }}</span>
12 <hr>
13 <p>{{ note['content'] |safe }}</p>
14 </div>
15 </div>
16 <hr>
17 {% endfor %}
18{% endblock %}
在这里,您扩展 base.html,定义一个标题,并使用一个 for 循环来浏览在 Bootstrap 卡中显示每个笔记的笔记,您显示笔记的 ID,笔记的创建日期和笔记的内容,您在 index() 视图中将其转换为 HTML。
您使用的 gcsafe Jinja 过滤器,您将其应用到使用 gcsafe的内容上;这类似于在 Python 中调用一个函数(类似于call(note(content))))。 callsafe 过滤器允许浏览器渲染 HTML 代码,如果没有应用,它会将 HTML 显示为纯文本。这通常被称为escaping HTML,这是一个防止恶意 HTML 在浏览器中被解释的安全特性,这会导致一个危险的安全漏洞,称为 cross-site scripting (XSS)。 由于 Python-Markdown 库返回了安全的 HTML,您可以允许浏览器使用callsafe 过滤器渲染它。 请记
有关更多信息,请阅读 Flask 关于 [控制自动逃避] 的文档(https://flask.palletsprojects.com/en/1.1.x/templating/#controlling-autoescaping)。
保存并关闭文件。
设置环境变量 Flask 需求,然后使用以下命令运行应用程序:
1export FLASK_APP=app
2export FLASK_ENV=development
3flask run
FLASK_APP环境变量指定你要运行的应用程序(app.py文件)。 FLASK_ENV环境变量指定模式;development意味着应用程序将在开发模式下运行,调试器运行(请记住避免在生产中使用这种模式)。
打开浏览器并输入URL http://127.0.0.1:5000/。

在这里,你会发现每个笔记在浏览器中被格式化和渲染为HTML,而不是简单的文本。
您创建了一个Flask应用程序,连接到数据库,收集笔记,将其内容从Markdown文本转换为HTML,然后在索引页面上渲染它们。
步骤 3 – 添加新笔记
在此步骤中,您将添加一个新的路径,允许用户创建新笔记. 用户可以使用 Markdown 语法来编写他们的笔记 — 您的应用程序将将笔记保存到数据库中,然后在索引页面上显示以适当的格式化。
您将使用网页表格允许用户在您的 Flask 应用程序中提交数据,并将用户提交的数据存储在您的数据库中。
首先打开app.py文件以添加新的路线:
1nano app.py
将下列代码添加到文件的末尾:
1[label flask_notes/app.py]
2#. . .
3
4@app.route('/create/', methods=('GET', 'POST'))
5def create():
6 conn = get_db_connection()
7
8 if request.method == 'POST':
9 content = request.form['content']
10 if not content:
11 flash('Content is required!')
12 return redirect(url_for('index'))
13 conn.execute('INSERT INTO notes (content) VALUES (?)', (content,))
14 conn.commit()
15 conn.close()
16 return redirect(url_for('index'))
17
18 return render_template('create.html')
由于您将使用此路线通过 Web 表单将新数据插入到数据库中,因此您可以使用 app.route() 装饰器中的 `methods=('GET', 'POST') 来允许 GET 和 POST 请求。
如果用户提交了一种表单,这意味着条件 request.method == 'POST' 是正确的,那么您会提取用户使用 request.form['content'] 提交的笔记内容,并将其保存到名为 content' 的变量中。如果内容是空的,则会闪烁一个 'Content is required!' 消息,并将用户重定向到索引页面。
如果请求是 GET 请求,这意味着用户刚刚访问了该页面,您会渲染一个名为 'create.html' 的模板文件。
保存并关闭文件。
接下来,打开create.html模板文件:
1nano templates/create.html
添加以下代码:
1[label flask_notes/templates/create.html]
2{% extends 'base.html' %}
3
4{% block content %}
5 <h1>{% block title %} Add a New Note {% endblock %}</h1>
6 <form method="post">
7 <div class="form-group">
8 <label for="content">Note Content</label>
9 <textarea type="text" name="content"
10 placeholder="Note content, you can use Markdown syntax" class="form-control"
11 value="{{ request.form['content'] }}" autofocus></textarea>
12 </div>
13
14 <div class="form-group">
15 <button type="submit" class="btn btn-primary">Submit</button>
16 </div>
17 </form>
18
19{% endblock %}
在这里,您使用具有文本区域的表单来记录笔记的内容. 您使用request.form访问存储的表单数据,以便在您的表单提交中发生错误的情况下(例如,如果没有提供内容)。
保存并关闭文件。
接下来打开base.html文件,将新笔记按钮添加到导航栏中:
1nano templates/base.html
用突出的代码编辑文件如下:
1[label flask_notes/templates/base.html]
2<!doctype html>
3<html lang="en">
4 <head>
5 <!-- Required meta tags -->
6 <meta charset="utf-8">
7 <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
8
9 <!-- Bootstrap CSS -->
10 <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
11
12 <title>{% block title %} {% endblock %}</title>
13 </head>
14 <body>
15 <nav class="navbar navbar-expand-md navbar-light bg-light">
16 <a class="navbar-brand" href="{{ url_for('index')}}">FlaskNotes</a>
17 <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
18 <span class="navbar-toggler-icon"></span>
19 </button>
20 <div class="collapse navbar-collapse" id="navbarNav">
21 <ul class="navbar-nav">
22 <li class="nav-item active">
23 <a class="nav-link" href="#">About</a>
24 </li>
25
26 <li class="nav-item active">
27 <a class="nav-link" href="{{ url_for('create') }}">New Note</a>
28 </li>
29 </ul>
30 </div>
31 </nav>
32 <div class="container">
33 {% for message in get_flashed_messages() %}
34 <div class="alert alert-danger">{{ message }}</div>
35 {% endfor %}
36 {% block content %} {% endblock %}
37 </div>
38
39 <!-- Optional JavaScript -->
40 <!-- jQuery first, then Popper.js, then Bootstrap JS -->
41 <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
42 <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
43 <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
44 </body>
45</html>
您可以使用url_for()函数将新的<li>项添加到导航栏中,以链接到create()视图函数。
运行开发服务器,如果您还没有:
1flask run
使用您的浏览器前往http://127.0.0.1:5000/create并添加以下标记:
1### Flask
2Flask is a **web** framework for _Python_.
3
4Here is the Flask logo:
5
6
这个标记包含一个h3标题,大胆的web字,意大利语的Python字和图像。
提交笔记,你会发现你的应用程序将其格式化为HTML。

您现在有一个新的路径,允许用户将新笔记添加到数据库中. 用户可以使用 Markdown 格式进行笔记,应用程序将在索引页面上显示 HTML 中的笔记。
您可以从 此存储库获取该应用程序的完整代码。
结论
您创建了一个 Flask 应用程序以在 Markdown 格式中创建笔记,以允许用户使用文本格式,如标题、大胆和语文本、添加图像和链接等。您将应用程序连接到 SQLite 数据库以存储和检索数据。您已将 Markdown 文本嵌入到 HTML 转换中,以便笔记在页面上进行渲染。 有关在 Python 中使用 Markdown 的更多信息,请参阅 How To Use Python-Markdown to Convert Markdown Text to HTML。
有关Flask的更多信息,请查看以下教程:
使用 Flask 和 SQLite 使用 One-to-Many Database Relationships 如何使用(https://andsky.com/tech/tutorials/how-to-use-one-to-many-database-relationships-with-flask-and-sqlite)。