Flask - 快速指南


烧瓶 – 概述

什么是网络框架?

Web 应用程序框架或简称 Web 框架代表库和模块的集合,使 Web 应用程序开发人员能够编写应用程序,而不必担心协议、线程管理等底层细节。

什么是烧瓶?

Flask 是一个用 Python 编写的 Web 应用程序框架。它由Armin Ronacher开发,他领导着一个名为 Pocco 的国际 Python 爱好者团体。Flask 基于 Werkzeug WSGI 工具包和 Jinja2 模板引擎。两者都是 Pocco 项目。

WSGI

Web 服务器网关接口 (WSGI) 已被采用作为 Python Web 应用程序开发的标准。WSGI 是 Web 服务器和 Web 应用程序之间通用接口的规范。

工厂

它是一个 WSGI 工具包,它实现了请求、响应对象和其他实用功能。这使得能够在其之上构建 Web 框架。Flask 框架使用 Werkzeug 作为其基础之一。

金贾2

Jinja2 是流行的 Python 模板引擎。Web 模板系统将模板与特定数据源结合起来以呈现动态网页。

Flask 通常被称为微框架。它的目的是保持应用程序的核心简单但可扩展。Flask 没有用于数据库处理的内置抽象层,也没有形成验证支持。相反,Flask 支持将此类功能添加到应用程序的扩展。本教程稍后将讨论一些流行的 Flask 扩展。

烧瓶 – 环境

先决条件

安装 Flask 通常需要 Python 2.6 或更高版本。尽管 Flask 及其依赖项可以很好地与 Python 3(Python 3.3 及以上版本)配合使用,但许多 Flask 扩展无法正确支持它。因此,建议在Python 2.7上安装Flask。

安装virtualenv作为开发环境

virtualenv是一个虚拟 Python 环境构建器。它可以帮助用户并行创建多个 Python 环境。从而可以避免不同版本库之间的兼容性问题。

以下命令安装virtualenv

pip install virtualenv

该命令需要管理员权限。在 Linux/Mac OS 上,在pip之前添加sudo 。如果您使用的是 Windows,请以管理员身份登录。在 Ubuntu 上,virtualenv可以使用其包管理器进行安装。

Sudo apt-get install virtualenv

安装后,将在文件夹中创建新的虚拟环境。

mkdir newproj
cd newproj
virtualenv venv

要激活相应的环境,在Linux/OS X上,使用以下命令 -

venv/bin/activate

在Windows上,可以使用以下内容

venv\scripts\activate

我们现在准备在这个环境中安装 Flask。

pip install Flask

上述命令可以直接运行,无需虚拟环境进行系统范围的安装。

烧瓶 – 应用

为了测试Flask安装,请在编辑器中键入以下代码Hello.py

from flask import Flask
app = Flask(__name__)

@app.route('/')
def hello_world():
   return 'Hello World’

if __name__ == '__main__':
   app.run()

项目中必须导入flask模块。Flask 类的一个对象是我们的WSGI应用程序。

Flask 构造函数将当前模块的名称(__name__) 作为参数。

Flask类的route()函数是一个装饰器,它告诉应用程序哪个URL应该调用关联的函数

app.route(rule, options)
  • 规则参数表示与函数的 URL 绑定

  • 选项是要转发到基础规则对象参数列表。

在上面的示例中,“/” URL 与hello_world()函数绑定。因此,当在浏览器中打开Web服务器的主页时,将呈现该函数的输出。

最后, Flask 类的run()方法在本地开发服务器上运行应用程序。

app.run(host, port, debug, options)

所有参数都是可选的

先生。 参数及说明
1

主持人

要监听的主机名。默认为 127.0.0.1(本地主机)。设置为“0.0.0.0”以使服务器在外部可用

2

港口

默认为 5000

3

调试

默认为 false。如果设置为 true,则提供调试信息

4

选项

转发到底层 Werkzeug 服务器。

上面给出的Python脚本是从 Python shell 执行的。

Python Hello.py

Python shell 中的一条消息通知您

* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)

在浏览器中打开上面的 URL (localhost:5000) 。其上将显示“Hello World”消息。

调试模式

Flask应用程序通过调用run()方法启动。然而,当应用程序正在开发时,每次代码更改都应该手动重新启动它。为了避免这种不便,请启用调试支持。如果代码更改,服务器将重新加载自身。它还将提供一个有用的调试器来跟踪应用程序中的错误(如果有)。

通过在运行之前将应用程序对象的 debug 属性设置为True将 debug 参数传递给run()方法,可以启用调试模式。

app.debug = True
app.run()
app.run(debug = True)

Flask – 路由

现代 Web 框架使用路由技术来帮助用户记住应用程序 URL。无需从主页导航即可直接访问所需页面,这非常有用。

Flask 中的route ()装饰器用于将 URL 绑定到函数。例如 -

@app.route(‘/hello’)
def hello_world():
   return ‘hello world’

这里,URL '/hello'规则绑定到hello_world()函数。因此,如果用户访问http://localhost:5000/hello URL, hello_world()函数的输出将在浏览器中呈现。

应用程序对象的add_url_rule ()函数也可用于将 URL 与函数绑定,如上例中使用的route() 。

装饰器的目的也可以通过以下表示来实现 -

def hello_world():
   return ‘hello world’
app.add_url_rule(‘/’, ‘hello’, hello_world)

Flask – 可变规则

通过向规则参数添加可变部分,可以动态构建 URL。该变量部分标记为<variable-name>。它作为关键字参数传递给与规则关联的函数。

在下面的示例中, route()装饰器的规则参数包含附加到 URL '/hello'的<name>变量部分。因此,如果在浏览器中输入http://localhost:5000/hello/TutorialsPoint作为URL ,则“TutorialPoint”将作为参数提供给hello()函数。

from flask import Flask
app = Flask(__name__)

@app.route('/hello/<name>')
def hello_name(name):
   return 'Hello %s!' % name

if __name__ == '__main__':
   app.run(debug = True)

将上述脚本保存为hello.py并从 Python shell 运行它。接下来,打开浏览器并输入 URL http://localhost:5000/hello/TutorialsPoint。

以下输出将显示在浏览器中。

Hello TutorialsPoint!

除了默认的字符串变量部分之外,还可以使用以下转换器构建规则 -

先生。 转换器及说明
1

整数

接受整数

2

漂浮

对于浮点值

3

小路

接受用作目录分隔符的斜杠

在下面的代码中,使用了所有这些构造函数。

from flask import Flask
app = Flask(__name__)

@app.route('/blog/<int:postID>')
def show_blog(postID):
   return 'Blog Number %d' % postID

@app.route('/rev/<float:revNo>')
def revision(revNo):
   return 'Revision Number %f' % revNo

if __name__ == '__main__':
   app.run()

从 Python Shell 运行上述代码。在浏览器中访问URL http://localhost:5000/blog/11 。

给定的数字用作show_blog()函数的参数。浏览器显示以下输出 -

Blog Number 11

在浏览器中输入此 URL - http://localhost:5000/rev/1.1

revision ()函数采用浮点数作为参数。以下结果出现在浏览器窗口中 -

Revision Number 1.100000

Flask 的 URL 规则基于Werkzeug 的路由模块。这可确保形成的 URL 是唯一的,并且基于 Apache 制定的先例。

考虑以下脚本中定义的规则 -

from flask import Flask
app = Flask(__name__)

@app.route('/flask')
def hello_flask():
   return 'Hello Flask'

@app.route('/python/')
def hello_python():
   return 'Hello Python'

if __name__ == '__main__':
   app.run()

这两个规则看起来很相似,但在第二个规则中,使用了尾部斜杠(/) 。结果,它成为规范的 URL。因此,使用/python/python/返回相同的输出。但是,在第一条规则的情况下,/flask/ URL 会导致404 Not Found页面。

Flask – URL 构建

url_for ()函数对于动态构建特定函数的 URL 非常有用。该函数接受函数名称作为第一个参数,以及一个或多个关键字参数,每个参数对应于 URL 的变量部分。

以下脚本演示了url_for()函数的使用。

from flask import Flask, redirect, url_for
app = Flask(__name__)

@app.route('/admin')
def hello_admin():
   return 'Hello Admin'

@app.route('/guest/<guest>')
def hello_guest(guest):
   return 'Hello %s as Guest' % guest

@app.route('/user/<name>')
def hello_user(name):
   if name =='admin':
      return redirect(url_for('hello_admin'))
   else:
      return redirect(url_for('hello_guest',guest = name))

if __name__ == '__main__':
   app.run(debug = True)

上面的脚本有一个函数user(name),它接受来自 URL 的参数值。

User ()函数检查接收到的参数是否与“admin”匹配。如果匹配,则应用程序将使用url_for()重定向到hello_admin()函数,否则重定向到hello_guest()函数,将收到的参数作为访客参数传递给它。

保存以上代码并从 Python shell 运行。

打开浏览器并输入 URL:http://localhost:5000/user/admin

浏览器中的应用程序响应是 -

Hello Admin

在浏览器中输入以下 URL - http://localhost:5000/user/mvl

应用程序响应现在更改为 -

Hello mvl as Guest

Flask – HTTP 方法

Http协议是万维网数据通信的基础。该协议定义了从指定 URL 检索数据的不同方法。

下表总结了不同的 http 方法 -

先生。 方法与说明
1

得到

以未加密的形式将数据发送到服务器。最常用的方法。

2

与 GET 相同,但没有响应正文

3

邮政

用于将 HTML 表单数据发送到服务器。服务器不会缓存通过 POST 方法接收的数据。

4

将目标资源的所有当前表示替换为上传的内容。

5

删除

删除 URL 给出的目标资源的所有当前表示

默认情况下,Flask 路由响应GET请求。但是,可以通过向route()装饰器提供方法参数来更改此首选项。

为了演示POST方法在 URL 路由中的使用,首先让我们创建一个 HTML 表单并使用POST方法将表单数据发送到 URL。

将以下脚本保存为login.html

<html>
   <正文>
      <表单操作=“http://localhost:5000/login”方法=“post”>
         <p>输入名称:</p>
         <p><输入类型=“文本”名称=“nm”/></p>
         <p><输入类型=“提交”值=“提交”/></p>
      </形式>
   </正文>
</html>

现在在 Python shell 中输入以下脚本。

从烧瓶导入烧瓶,重定向,url_for,请求
应用程序=烧瓶(__名称__)

@app.route('/成功/<名称>')
def 成功(名称):
   返回 '​​欢迎 %s' % 名称

@app.route('/login',methods = ['POST', 'GET'])
def 登录():
   如果 request.method == 'POST':
      用户 = request.form['nm']
      返回重定向(url_for('成功',名称=用户))
   别的:
      用户 = request.args.get('nm')
      返回重定向(url_for('成功',名称=用户))

如果 __name__ == '__main__':
   应用程序运行(调试= True)

开发服务器开始运行后,在浏览器中打开login.html ,在文本字段中输入名称,然后单击提交

后置方法示例

表单数据被 POST 到表单标签的 action 子句中的 URL。

http://localhost/login映射到login()函数。由于服务器已通过POST方法接收数据,因此从表单数据中获取的“nm”参数值通过以下方式获得:

用户 = request.form['nm']

它作为变量部分传递到“/success” URL。浏览器在窗口中显示欢迎消息。

欢迎辞

将login.html中的方法参数更改为“GET”,然后在浏览器中再次打开。服务器通过GET方法接收数据。“nm”参数的值现在通过以下方式获得 -

用户 = request.args.get('nm')

这里,args是字典对象,包含表单参数对及其相应值的列表。与之前一样,与“nm”参数对应的值将传递到“/success”URL。

Flask – 模板

可以以 HTML 的形式返回绑定到某个 URL 的函数的输出。例如,在下面的脚本中,hello()函数将渲染“Hello World”并附加<h1>标签。

from flask import Flask
app = Flask(__name__)

@app.route('/')
def index():
   return '<html><body><h1>Hello World</h1></body></html>'

if __name__ == '__main__':
   app.run(debug = True)

然而,从 Python 代码生成 HTML 内容很麻烦,尤其是当需要放置变量数据和条件或循环等 Python 语言元素时。这需要频繁地从 HTML 中转义。

这就是可以利用Flask 所基于的Jinja2模板引擎的地方。HTML 文件可以通过render_template()函数呈现,而不是从函数返回硬编码 HTML 。

from flask import Flask
app = Flask(__name__)

@app.route('/')
def index():
   return render_template(‘hello.html’)

if __name__ == '__main__':
   app.run(debug = True)

Flask 将尝试在 templates 文件夹中查找 HTML 文件,该文件夹位于该脚本所在的同一文件夹中。

  • 应用程序文件夹
    • 你好.py
    • 模板
      • 你好.html

术语“Web 模板系统”是指设计可以动态插入可变数据的 HTML 脚本。Web模板系统由模板引擎、某种数据源和模板处理器组成。

Flask 使用Jinja2模板引擎。Web 模板包含散布变量和表达式(在本例中为 Python 表达式)的 HTML 语法占位符,这些占位符在呈现模板时将被替换。

以下代码在模板文件夹中保存为hello.html 。

<!doctype html>
<html>
   <body>
   
      <h1>Hello {{ name }}!</h1>
      
   </body>
</html>

接下来,从 Python shell 运行以下脚本。

from flask import Flask, render_template
app = Flask(__name__)

@app.route('/hello/<user>')
def hello_name(user):
   return render_template('hello.html', name = user)

if __name__ == '__main__':
   app.run(debug = True)

当开发服务器开始运行时,打开浏览器并输入 URL:http://localhost:5000/hello/mvl

URL 的变量部分插入到{{ name }}占位符处。

网页模板系统示例

Jinja2模板引擎使用以下分隔符来转义 HTML。

  • {% ... %} 用于语句
  • {{ ... }} 用于打印到模板输出的表达式
  • {# ... #} 表示未包含在模板输出中的注释
  • # ... ## 用于行语句

在以下示例中,演示了模板中条件语句的使用。hello()函数的 URL 规则接受整数参数。它被传递到hello.html模板。在其中,比较收到的数字(标记)的值(大于或小于 50),并相应地有条件地呈现 HTML。

Python 脚本如下 -

from flask import Flask, render_template
app = Flask(__name__)

@app.route('/hello/<int:score>')
def hello_name(score):
   return render_template('hello.html', marks = score)

if __name__ == '__main__':
   app.run(debug = True)

hello.html的 HTML 模板脚本如下 -

<!doctype html>
<html>
   <body>
      {% if marks>50 %}
         <h1> Your result is pass!</h1>
      {% else %}
         <h1>Your result is fail</h1>
      {% endif %}
   </body>
</html>

请注意,条件语句if-elseendif包含在分隔符{%..%}中。

运行 Python 脚本并访问 URL http://localhost/hello/60,然后访问 http://localhost/hello/30以查看有条件更改的 HTML 输出。

Python 循环结构也可以在模板内部使用。在以下脚本中,当在浏览器中打开URL http://localhost:5000/result时, result()函数将字典对象发送到模板results.html 。

result.html的模板部分使用for 循环将字典对象result{}的键和值对呈现为 HTML 表的单元格。

从 Python shell 运行以下代码。

from flask import Flask, render_template
app = Flask(__name__)

@app.route('/result')
def result():
   dict = {'phy':50,'che':60,'maths':70}
   return render_template('result.html', result = dict)

if __name__ == '__main__':
   app.run(debug = True)

将以下 HTML 脚本保存为templates 文件夹中的result.html 。

<!doctype html>
<html>
   <body>
      <table border = 1>
         {% for key, value in result.items() %}
            <tr>
               <th> {{ key }} </th>
               <td> {{ value }} </td>
            </tr>
         {% endfor %}
      </table>
   </body>
</html>

在这里,与For循环相对应的 Python 语句再次包含在 {%..%} 中,而表达式key 和 value则放在{{ }}内。

开发开始运行后,在浏览器中打开http://localhost:5000/result,得到以下输出。

表格模板示例

Flask – 静态文件

Web 应用程序通常需要静态文件,例如支持网页显示的JavaScript文件或CSS文件。通常,Web 服务器被配置为为您提供服务,但在开发过程中,这些文件是从包中或模块旁边的static文件夹提供的,并且可以在应用程序的/static中找到。

特殊端点“static”用于生成静态文件的 URL。

在以下示例中,在index.html中的 HTML 按钮的OnClick事件上调用hello.js中定义的javascript函数,该按钮在Flask 应用程序的“/” URL上呈现。

from flask import Flask, render_template
app = Flask(__name__)

@app.route("/")
def index():
   return render_template("index.html")

if __name__ == '__main__':
   app.run(debug = True)

下面给出了index.html的HTML 脚本。

<html>
   <head>
      <script type = "text/javascript" 
         src = "{{ url_for('static', filename = 'hello.js') }}" ></script>
   </head>
   
   <body>
      <input type = "button" onclick = "sayHello()" value = "Say Hello" />
   </body>
</html>

hello.js包含sayHello()函数。

function sayHello() {
   alert("Hello World")
}

Flask – 请求对象

来自客户端网页的数据作为全局请求对象发送到服务器。为了处理请求数据,应该从Flask模块导入。

下面列出了请求对象的重要属性 -

  • 表单- 它是一个字典对象,包含表单参数及其值的键和值对。

  • args - 解析后的查询字符串的内容,该字符串是问号 (?) 之后 URL 的一部分。

  • Cookies - 保存 Cookie 名称和值的字典对象。

  • 文件- 与上传文件有关的数据。

  • method - 当前请求方法。

Flask – 将表单数据发送到模板

我们已经看到可以在 URL 规则中指定 http 方法。触发的函数接收到的表单数据可以以字典对象的形式收集并转发到模板以呈现在相应的网页上。

在以下示例中,“/” URL 呈现一个具有表单的网页 (student.html)。填写的数据将发布到触发result()函数的“/result” URL 。

results ()函数收集字典对象中request.form中存在的表单数据,并将其发送到result.html进行渲染。

该模板动态呈现表单数据的 HTML 表。

下面给出的是应用程序的 Python 代码 -

from flask import Flask, render_template, request
app = Flask(__name__)

@app.route('/')
def student():
   return render_template('student.html')

@app.route('/result',methods = ['POST', 'GET'])
def result():
   if request.method == 'POST':
      result = request.form
      return render_template("result.html",result = result)

if __name__ == '__main__':
   app.run(debug = True)

下面给出的是Student.html的 HTML 脚本。

<html>
   <body>
      <form action = "http://localhost:5000/result" method = "POST">
         <p>Name <input type = "text" name = "Name" /></p>
         <p>Physics <input type = "text" name = "Physics" /></p>
         <p>Chemistry <input type = "text" name = "chemistry" /></p>
         <p>Maths <input type ="text" name = "Mathematics" /></p>
         <p><input type = "submit" value = "submit" /></p>
      </form>
   </body>
</html>

模板代码(result.html)如下:

<!doctype html>
<html>
   <body>
      <table border = 1>
         {% for key, value in result.items() %}
            <tr>
               <th> {{ key }} </th>
               <td> {{ value }} </td>
            </tr>
         {% endfor %}
      </table>
   </body>
</html>

运行Python脚本并在浏览器中输入URL http://localhost:5000/ 。

提交分数

单击“提交”按钮后,表单数据将以HTML 表格的形式呈现在result.html上。

分数表

烧瓶 – cookie

cookie 以文本文件的形式存储在客户端的计算机上。其目的是记住和跟踪与客户使用情况相关的数据,以获得更好的访问者体验和网站统计数据。

Request 对象包含cookie 的属性。它是客户端传输的所有 cookie 变量及其相应值的字典对象。除此之外,cookie 还存储其到期时间、站点路径和域名。

在 Flask 中,cookie 是在响应对象上设置的。使用make_response()函数从视图函数的返回值中获取响应对象。之后,使用响应对象的set_cookie()函数来存储cookie。

读回 cookie 很容易。request.cookies属性的get()方法用于读取cookie。

在以下 Flask 应用程序中,当您访问“/” URL 时,会打开一个简单的表单。

@app.route('/')
def index():
   return render_template('index.html')

此 HTML 页面包含一个文本输入。

<html>
   <body>
      <form action = "/setcookie" method = "POST">
         <p><h3>Enter userID</h3></p>
         <p><input type = 'text' name = 'nm'/></p>
         <p><input type = 'submit' value = 'Login'/></p>
      </form>
   </body>
</html>

该表单将发布到“/setcookie” URL。关联的视图函数设置 Cookie 名称userID并呈现另一个页面。

@app.route('/setcookie', methods = ['POST', 'GET'])
def setcookie():
   if request.method == 'POST':
   user = request.form['nm']
   
   resp = make_response(render_template('readcookie.html'))
   resp.set_cookie('userID', user)
   
   return resp

“readcookie.html”包含指向另一个视图函数getcookie()的超链接,该函数在浏览器中读回并显示 cookie 值。

@app.route('/getcookie')
def getcookie():
   name = request.cookies.get('userID')
   return '<h1>welcome '+name+'</h1>'

运行应用程序并访问http://localhost:5000/

读取 Cookie HTML

设置 cookie 的结果显示如下 -

设置Cookie的结果

读回cookie的输出如下所示。

读取 Cookie 返回

Flask – 会话

与 Cookie 一样,Session 数据存储在客户端。会话是客户端登录到服务器和注销服务器的时间间隔。在此会话期间需要保存的数据存储在客户端浏览器中。

每个客户端的会话都会分配一个会话 ID。会话数据存储在 cookie 之上,服务器以加密方式对它们进行签名。对于这种加密,Flask 应用程序需要定义一个SECRET_KEY

Session 对象也是一个字典对象,包含会话变量的键值对和关联值。

例如,要设置“用户名”会话变量,请使用以下语句 -

Session[‘username’] = ’admin’

要释放会话变量,请使用pop()方法。

session.pop('username', None)

下面的代码是 Flask 中会话工作的简单演示。URL “/”只是提示用户登录,因为未设置会话变量“用户名” 。

@app.route('/')
def index():
   if 'username' in session:
      username = session['username']
         return 'Logged in as ' + username + '<br>' + \
         "<b><a href = '/logout'>click here to log out</a></b>"
   return "You are not logged in <br><a href = '/login'></b>" + \
      "click here to log in</b></a>"

当用户浏览到“/login”时,login() 视图函数会打开一个登录表单,因为它是通过 GET 方法调用的。

表单被发送回“/login”,现在会话变量已设置。应用程序被重定向到'/'。这次找到会话变量“用户名” 。

@app.route('/login', methods = ['GET', 'POST'])
def login():
   if request.method == 'POST':
      session['username'] = request.form['username']
      return redirect(url_for('index'))
   return '''
	
   <form action = "" method = "post">
      <p><input type = text name = username/></p>
      <p<<input type = submit value = Login/></p>
   </form>
	
   '''

该应用程序还包含一个logout()视图函数,它会弹出“用户名”会话变量。因此,“/” URL 再次显示打开页面。

@app.route('/logout')
def logout():
   # remove the username from the session if it is there
   session.pop('username', None)
   return redirect(url_for('index'))

运行应用程序并访问主页。(确保设置应用程序的secret_key )

from flask import Flask, session, redirect, url_for, escape, request
app = Flask(__name__)
app.secret_key = 'any random string’

输出将如下所示显示。单击链接“单击此处登录”

使用会话的登录页面

该链接将被定向到另一个屏幕。输入“管理员”。

另一个登录屏幕

屏幕将显示消息“以管理员身份登录”

以管理员身份登录

Flask – 重定向和错误

Flask 类有一个redirect()函数。调用时,它返回一个响应对象,并将用户重定向到具有指定状态代码的另一个目标位置。

redirect()函数的原型如下 -

Flask.redirect(location, statuscode, response)

在上面的函数中 -

  • location参数是应将响应重定向到的 URL。

  • 发送到浏览器标头的状态码,默认为 302。

  • 响应参数用于实例化响应。

以下状态代码是标准化的 -

  • HTTP_300_MULTIPLE_CHOICES
  • HTTP_301_MOVED_PERMANENTLY
  • HTTP_302_FOUND
  • HTTP_303_SEE_OTHER
  • HTTP_304_NOT_MODIFIED
  • HTTP_305_USE_PROXY
  • HTTP_306_RESERVED
  • HTTP_307_TEMPORARY_REDIRECT

默认状态代码是302,代表'found'

在以下示例中,redirect()函数用于在登录尝试失败时再次显示登录页面。

from flask import Flask, redirect, url_for, render_template, request
# Initialize the Flask application
app = Flask(__name__)

@app.route('/')
def index():
   return render_template('log_in.html')

@app.route('/login',methods = ['POST', 'GET']) 
def login(): 
   if request.method == 'POST' and request.form['username'] == 'admin' :
      return redirect(url_for('success'))
   else:
      return redirect(url_for('index'))

@app.route('/success')
def success():
   return 'logged in successfully'
	
if __name__ == '__main__':
   app.run(debug = True)

Flask 类具有带有错误代码的abort()函数。

Flask.abort(code)

Code参数采用以下值之一-

  • 400 - 错误请求

  • 401 - 未经身份验证

  • 403 - 禁止

  • 404 - 未找到

  • 406 - 不可接受

  • 415 - 不支持的媒体类型

  • 429 - 请求太多

让我们对上面代码中的login()函数稍作修改。如果要显示“未经授权”页面,请将其替换为对abort(401)的调用,而不是重新显示登录页面。

from flask import Flask, redirect, url_for, render_template, request, abort
app = Flask(__name__)

@app.route('/')
def index():
   return render_template('log_in.html')

@app.route('/login',methods = ['POST', 'GET'])
def login():
   if request.method == 'POST':
      if request.form['username'] == 'admin' :
         return redirect(url_for('success'))
      else:
         abort(401)
   else:
      return redirect(url_for('index'))

@app.route('/success')
def success():
   return 'logged in successfully'

if __name__ == '__main__':
   app.run(debug = True)

Flask – 消息闪烁

一个好的基于 GUI 的应用程序可以向用户提供有关交互的反馈。例如,桌面应用程序使用对话框或消息框,而 JavaScript 使用警报来实现类似的目的。

在 Flask Web 应用程序中生成此类信息性消息很容易。Flask 框架的 Flash 系统使得在一个视图中创建消息并在名为next的视图函数中渲染它成为可能。

Flask 模块包含flash()方法。它将一条消息传递给下一个请求,该请求通常是一个模板。

flash(message, category)

这里,

  • message参数是要闪烁的实际消息。

  • 类别参数是可选的。它可以是“错误”、“信息”或“警告”。

为了从会话中删除消息,模板调用get_flashed_messages()

get_flashed_messages(with_categories, category_filter)

这两个参数都是可选的。如果收到的消息有类别,则第一个参数是一个元组。第二个参数对于仅显示特定消息很有用。

以下闪烁模板中收到的消息。

{% with messages = get_flashed_messages() %}
   {% if messages %}
      {% for message in messages %}
         {{ message }}
      {% endfor %}
   {% endif %}
{% endwith %}

现在让我们看一个简单的例子,演示 Flask 中的闪烁机制。在以下代码中,“/” URL 显示登录页面的链接,不显示任何消息。

@app.route('/')
def index():
   return render_template('index.html')

该链接将用户引导至显示登录表单的“/login” URL。提交后,login()视图函数会验证用户名和密码,并相应地闪烁“成功”消息或创建“错误”变量。

@app.route('/login', methods = ['GET', 'POST'])
def login():
   error = None
   
   if request.method == 'POST':
      if request.form['username'] != 'admin' or \
         request.form['password'] != 'admin':
         error = 'Invalid username or password. Please try again!'
      else:
         flash('You were successfully logged in')
         return redirect(url_for('index'))
   return render_template('login.html', error = error)

如果出现错误,登录模板将重新显示并显示错误消息。

登录.html

<!doctype html>
<html>
   <body>
      <h1>Login</h1>

      {% if error %}
         <p><strong>Error:</strong> {{ error }}
      {% endif %}
      
      <form action = "" method = post>
         <dl>
            <dt>Username:</dt>
            <dd>
               <input type = text name = username 
                  value = "{{request.form.username }}">
            </dd>
            <dt>Password:</dt>
            <dd><input type = password name = password></dd>
         </dl>
         <p><input type = submit value = Login></p>
      </form>
   </body>
</html>

另一方面,如果登录成功,索引模板上会闪烁成功消息。

索引.html

<!doctype html>
<html>
   <head>
      <title>Flask Message flashing</title>
   </head>
   <body>
      {% with messages = get_flashed_messages() %}
         {% if messages %}
            <ul>
               {% for message in messages %}
               <li<{{ message }}</li>
               {% endfor %}
            </ul>
         {% endif %}
      {% endwith %}
		
      <h1>Flask Message Flashing Example</h1>
      <p>Do you want to <a href = "{{ url_for('login') }}">
         <b>log in?</b></a></p>
   </body>
</html>

Flask 消息闪烁示例的完整代码如下 -

闪存.py

from flask import Flask, flash, redirect, render_template, request, url_for
app = Flask(__name__)
app.secret_key = 'random string'

@app.route('/')
def index():
   return render_template('index.html')

@app.route('/login', methods = ['GET', 'POST'])
def login():
   error = None
   
   if request.method == 'POST':
      if request.form['username'] != 'admin' or \
         request.form['password'] != 'admin':
         error = 'Invalid username or password. Please try again!'
      else:
         flash('You were successfully logged in')
         return redirect(url_for('index'))
			
   return render_template('login.html', error = error)

if __name__ == "__main__":
   app.run(debug = True)

执行以上代码后,您将看到如下所示的屏幕。

Flask 消息闪烁示例

当您点击该链接时,您将被引导至登录页面。

输入用户名和密码。

登录页面

单击“登录”。将显示一条消息“您已成功登录”。

成功登录页面

Flask – 文件上传

在 Flask 中处理文件上传非常简单。它需要一个 HTML 表单,并将其 enctype 属性设置为“multipart/form-data”,将文件发布到 URL。URL 处理程序从request.files[]对象获取文件并将其保存到所需位置。

每个上传的文件首先保存在服务器上的临时位置,然后才实际保存到其最终位置。目标文件的名称可以是硬编码的,也可以从request.files[file]对象的 filename 属性中获取。但是,建议使用secure_filename()函数获取它的安全版本。

可以在 Flask 对象的配置设置中定义默认上传文件夹的路径和上传文件的最大大小。

app.config['UPLOAD_FOLDER'] 定义上传文件夹的路径
app.config['MAX_CONTENT_PATH'] 指定要上传的文件的最大大小 - 以字节为单位

以下代码具有显示模板文件夹中的“upload.html”的“/upload”URL 规则,以及调用处理上传过程的 uploader() 函数的“/upload- file ” URL规则

“upload.html”有一个文件选择器按钮和一个提交按钮。

<html>
   <body>
      <form action = "http://localhost:5000/uploader" method = "POST" 
         enctype = "multipart/form-data">
         <input type = "file" name = "file" />
         <input type = "submit"/>
      </form>
   </body>
</html>

您将看到如下所示的屏幕。

Flask 文件上传

选择文件后点击提交。表单的 post 方法调用“/upload_file” URL。底层函数uploader()执行保存操作。

以下是 Flask 应用程序的 Python 代码。

from flask import Flask, render_template, request
from werkzeug import secure_filename
app = Flask(__name__)

@app.route('/upload')
def upload_file():
   return render_template('upload.html')
	
@app.route('/uploader', methods = ['GET', 'POST'])
def upload_file():
   if request.method == 'POST':
      f = request.files['file']
      f.save(secure_filename(f.filename))
      return 'file uploaded successfully'
		
if __name__ == '__main__':
   app.run(debug = True)

Flask – 扩展

Flask 通常被称为微框架,因为核心功能包括基于Werkzeug 的WSGI 和路由以及基于Jinja2 的模板引擎。此外,Flask 框架还支持 cookie 和会话以及JSON、静态文件等 Web 帮助程序。显然,这对于开发成熟的 Web 应用程序来说是不够的。这就是 Flask 扩展发挥作用的地方。Flask 扩展为 Flask 框架提供了可扩展性。

有大量可用的 Flask 扩展。Flask 扩展是一个 Python 模块,它为 Flask 应用程序添加了特定类型的支持。Flask 扩展注册表是可用扩展的目录。所需的扩展可以通过pip实用程序下载。

在本教程中,我们将讨论以下重要的 Flask 扩展 -

  • Flask Mail - 为 Flask 应用程序提供 SMTP 接口

  • Flask WTF - 添加 WTForms 的渲染和验证

  • Flask SQLAlchemy - 向 Flask 应用程序添加 SQLAlchemy 支持

  • Flask Sijax - Sijax 接口 - Python/jQuery 库,使 AJAX 在 Web 应用程序中易于使用

每种类型的扩展通常都提供有关其用法的大量文档。由于扩展是一个 Python 模块,因此需要导入它才能使用。Flask 扩展通常命名为flask-foo。要导入,

from flask_foo import [class, function]

对于 Flask 0.7 之后的版本,您还可以使用语法 -

from flask.ext import foo

对于此用途,需要激活兼容性模块。可以通过运行flaskext_compat.py来安装

import flaskext_compat
flaskext_compat.activate()
from flask.ext import foo

烧瓶 – 邮件

基于 Web 的应用程序通常需要具有向用户/客户端发送邮件的功能。Flask-Mail扩展使得与任何电子邮件服务器建立简单的界面变得非常容易。

首先,应在 pip 实用程序的帮助下安装 Flask-Mail 扩展。

pip install Flask-Mail

然后需要通过设置以下应用程序参数的值来配置 Flask-Mail。

先生编号 参数及说明
1

邮件服务器

电子邮件服务器的名称/IP 地址

2

邮件端口

使用的服务器端口号

3

MAIL_USE_TLS

启用/禁用传输安全层加密

4

MAIL_USE_SSL

启用/禁用安全套接字层加密

5

邮件调试

调试支持。默认为 Flask 应用程序的调试状态

6

MAIL_USERNAME

发件人的用户名

7

邮件密码

发件人密码

8

MAIL_DEFAULT_SENDER

设置默认发件人

9

MAIL_MAX_EMAILS

设置要发送的最大邮件数

10

MAIL_SUPPRESS_SEND

如果 app.testing 设置为 true,则发送被抑制

11

MAIL_ASCII_ATTACHMENTS

如果设置为 true,附加文件名将转换为 ASCII

Flask-mail 模块包含以下重要类的定义。

邮件类

它管理电子邮件消息传递要求。类构造函数采用以下形式 -

flask-mail.Mail(app = None)

构造函数将 Flask 应用程序对象作为参数。

Mail类的方法

先生编号 方法与说明
1

发送()

发送 Message 类对象的内容

2

连接()

打开与邮件主机的连接

3

发信息()

发送消息对象

消息类

它封装了电子邮件消息。消息类构造函数有几个参数 -

flask-mail.Message(subject, recipients, body, html, sender, cc, bcc, 
   reply-to, date, charset, extra_headers, mail_options, rcpt_options)

消息类方法

Attach() - 将附件添加到消息中。该方法采用以下参数 -

  • filename - 要附加的文件名

  • content_type - 文件的 MIME 类型

  • 数据- 原始文件数据

  • 处置- 内容处置(如果有)。

add_recipient() - 将另一个收件人添加到消息中

在下面的示例中,Google gmail 服务的 SMTP 服务器用作 Flask-Mail 配置的 MAIL_SERVER。

步骤 1 - 从代码中的 Flask-mail 模块导入 Mail 和 Message 类。

from flask_mail import Mail, Message

步骤 2 - 然后按照以下设置配置 Flask-Mail。

app.config['MAIL_SERVER']='smtp.gmail.com'
app.config['MAIL_PORT'] = 465
app.config['MAIL_USERNAME'] = 'yourId@gmail.com'
app.config['MAIL_PASSWORD'] = '*****'
app.config['MAIL_USE_TLS'] = False
app.config['MAIL_USE_SSL'] = True

步骤 3 - 创建 Mail 类的实例。

mail = Mail(app)

步骤 4 - 在由 URL 规则('/')映射的 Python 函数中设置 Message 对象。

@app.route("/")
def index():
   msg = Message('Hello', sender = 'yourId@gmail.com', recipients = ['id1@gmail.com'])
   msg.body = "This is the email body"
   mail.send(msg)
   return "Sent"

步骤 5 - 完整代码如下。在 Python Shell 中运行以下脚本并访问http://localhost:5000/。

from flask import Flask
from flask_mail import Mail, Message

app =Flask(__name__)
mail=Mail(app)

app.config['MAIL_SERVER']='smtp.gmail.com'
app.config['MAIL_PORT'] = 465
app.config['MAIL_USERNAME'] = 'yourId@gmail.com'
app.config['MAIL_PASSWORD'] = '*****'
app.config['MAIL_USE_TLS'] = False
app.config['MAIL_USE_SSL'] = True
mail = Mail(app)

@app.route("/")
def index():
   msg = Message('Hello', sender = 'yourId@gmail.com', recipients = ['id1@gmail.com'])
   msg.body = "Hello Flask message sent from Flask-Mail"
   mail.send(msg)
   return "Sent"

if __name__ == '__main__':
   app.run(debug = True)

请注意,Gmail 服务中的内置安全功能可能会阻止此登录尝试。您可能必须降低安全级别。请登录您的 Gmail 帐户并访问链接以降低安全性。

降低安全性

烧瓶 – WTF

Web 应用程序的基本方面之一是为用户呈现用户界面。HTML提供了<form>标签,用于设计界面。可以适当使用表单元素,例如文本输入、单选、选择等。

用户输入的数据通过 GET 或 POST 方法以 Http 请求消息的形式提交到服务器端脚本。

  • 服务器端脚本必须从 http 请求数据重新创建表单元素。因此,实际上,表单元素必须定义两次——一次在 HTML 中,另一次在服务器端脚本中。

  • 使用 HTML 表单的另一个缺点是很难(如果不是不可能的话)动态呈现表单元素。HTML 本身不提供验证用户输入的方法。

这就是WTForms这个灵活的表单、渲染和验证库派上用场的地方。Flask-WTF 扩展为此WTForms库提供了一个简单的接口。

使用Flask-WTF,我们可以在 Python 脚本中定义表单字段并使用 HTML 模板呈现它们。还可以对WTF字段应用验证。

让我们看看动态生成 HTML 是如何工作的。

首先,需要安装 Flask-WTF 扩展。

pip install flask-WTF

安装的包包含一个Form类,必须将其用作用户定义表单的父级。

WTforms包包含各种表单字段的定义。下面列出了一些标准表单字段。

先生编号 标准表单字段和说明
1

文本域

代表 <input type='text'> HTML 表单元素

2

布尔字段

代表 <input type='checkbox'> HTML 表单元素

3

小数域

用于显示带小数的数字的文本字段

4

整数字段

用于显示整数的文本字段

5

无线电场

代表 <input type='radio'> HTML 表单元素

6

选择字段

代表选择表单元素

7

文本区域字段

代表 <testarea> html 表单元素

8

密码字段

代表 <input type='password'> HTML 表单元素

9

提交字段

代表<input type='submit'>表单元素

例如,包含文本字段的表单可以设计如下 -

from flask_wtf import Form
from wtforms import TextField

class ContactForm(Form):
   name = TextField("Name Of Student")

除了“名称”字段之外,还会自动创建 CSRF 令牌的隐藏字段。这是为了防止跨站请求伪造攻击。

渲染后,这将生成等效的 HTML 脚本,如下所示。

<input id = "csrf_token" name = "csrf_token" type = "hidden" />
<label for = "name">Name Of Student</label><br>
<input id = "name" name = "name" type = "text" value = "" />

Flask 应用程序中使用用户定义的表单类,并使用模板呈现表单。

from flask import Flask, render_template
from forms import ContactForm
app = Flask(__name__)
app.secret_key = 'development key'

@app.route('/contact')
def contact():
   form = ContactForm()
   return render_template('contact.html', form = form)

if __name__ == '__main__':
   app.run(debug = True)

WTForms 包还包含验证器类。它对于将验证应用于表单字段非常有用。以下列表显示了常用的验证器。

先生编号 验证器类和描述
1

所需数据

检查输入字段是否为空

2

电子邮件

检查字段中的文本是否遵循电子邮件 ID 约定

3

IP地址

验证输入字段中的 IP 地址

4

长度

验证输入字段中字符串的长度是否在给定范围内

5

数字范围

验证输入字段中给定范围内的数字

6

网址

验证在输入字段中输入的 URL

我们现在将为联系表单中的姓名字段应用“DataRequired”验证规则。

name = TextField("Name Of Student",[validators.Required("Please enter your name.")])

表单对象的validate ()函数验证表单数据,如果验证失败则抛出验证错误。错误消息将发送到模板。在 HTML 模板中,错误消息是动态呈现的。

{% for message in form.name.errors %}
   {{ message }}
{% endfor %}

以下示例演示了上面给出的概念。联系表单的设计如下(forms.py)

from flask_wtf import Form
from wtforms import TextField, IntegerField, TextAreaField, SubmitField, RadioField,
   SelectField

from wtforms import validators, ValidationError

class ContactForm(Form):
   name = TextField("Name Of Student",[validators.Required("Please enter 
      your name.")])
   Gender = RadioField('Gender', choices = [('M','Male'),('F','Female')])
   Address = TextAreaField("Address")
   
   email = TextField("Email",[validators.Required("Please enter your email address."),
      validators.Email("Please enter your email address.")])
   
   Age = IntegerField("age")
   language = SelectField('Languages', choices = [('cpp', 'C++'), 
      ('py', 'Python')])
   submit = SubmitField("Send")

验证器应用于“名称”“电子邮件”字段。

下面给出的是 Flask 应用程序脚本(formexample.py)

from flask import Flask, render_template, request, flash
from forms import ContactForm
app = Flask(__name__)
app.secret_key = 'development key'

@app.route('/contact', methods = ['GET', 'POST'])
def contact():
   form = ContactForm()
   
   if request.method == 'POST':
      if form.validate() == False:
         flash('All fields are required.')
         return render_template('contact.html', form = form)
      else:
         return render_template('success.html')
      elif request.method == 'GET':
         return render_template('contact.html', form = form)

if __name__ == '__main__':
   app.run(debug = True)

模板的脚本(contact.html)如下 -

<!doctype html>
<html>
   <body>
      <h2 style = "text-align: center;">Contact Form</h2>
		
      {% for message in form.name.errors %}
         <div>{{ message }}</div>
      {% endfor %}
      
      {% for message in form.email.errors %}
         <div>{{ message }}</div>
      {% endfor %}
      
      <form action = "http://localhost:5000/contact" method = post>
         <fieldset>
            <legend>Contact Form</legend>
            {{ form.hidden_tag() }}
            
            <div style = font-size:20px; font-weight:bold; margin-left:150px;>
               {{ form.name.label }}<br>
               {{ form.name }}
               <br>
               
               {{ form.Gender.label }} {{ form.Gender }}
               {{ form.Address.label }}<br>
               {{ form.Address }}
               <br>
               
               {{ form.email.label }}<br>
               {{ form.email }}
               <br>
               
               {{ form.Age.label }}<br>
               {{ form.Age }}
               <br>
               
               {{ form.language.label }}<br>
               {{ form.language }}
               <br>
               {{ form.submit }}
            </div>
            
         </fieldset>
      </form>
   </body>
</html>

在 Python shell 中运行formexample.py并访问 URL http://localhost:5000/contact联系表格将显示如下。

表格示例

如果有任何错误,页面将如下所示 -

表单错误页面

如果没有错误,将呈现“success.html” 。

表单成功页面

Flask——SQLite

Python 内置了对SQlite的支持。SQlite3 模块随 Python 发行版一起提供。有关在Python中使用SQLite数据库的详细教程,请参考此链接。在本节中,我们将了解 Flask 应用程序如何与 SQLite 交互。

创建一个 SQLite 数据库“database.db”并在其中创建一个学生表。

import sqlite3

conn = sqlite3.connect('database.db')
print "Opened database successfully";

conn.execute('CREATE TABLE students (name TEXT, addr TEXT, city TEXT, pin TEXT)')
print "Table created successfully";
conn.close()

我们的 Flask 应用程序具有三个视图函数。

第一个new_student()函数绑定到 URL 规则('/addnew')。它呈现一个包含学生信息表单的 HTML 文件。

@app.route('/enternew')
def new_student():
   return render_template('student.html')

“student.html”的 HTML 脚本如下 -

<html>
   <body>
      <form action = "{{ url_for('addrec') }}" method = "POST">
         <h3>Student Information</h3>
         Name<br>
         <input type = "text" name = "nm" /></br>
         
         Address<br>
         <textarea name = "add" ></textarea><