程序猿哥哥带你快速入门Flask框架

Posted Amo Xiang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了程序猿哥哥带你快速入门Flask框架相关的知识,希望对你有一定的参考价值。

一、Flask 基础

【示例1】编写第一个Flask程序,代码如下:

from flask import Flask  # 1.导入Flask类

"""
2.创建该类的一个实例。第一个参数是应用模块或者包的名称。如果使用单一的模块(如此处),则应该使用__name__。
模块的名称将会因其作为单独应用启动还是作为模块导入而有所不同。这样Flask才知道到哪去找模板、静态文件等。
"""
app = Flask(__name__)


@app.route("/")  # 3.使用route()装饰器函数告诉Flask什么样的URL能触发被执行的函数
def index():  # 4.视图函数,返回显示在用户浏览器中的信息。
    return 'Hello Flask!'


# app.debug = True 第一种方式:开启调试模式

if __name__ == '__main__':
    app.run(debug=True, port=8000)  # 第二种方式:作为run()方法的一个参数传入 也可以设置其他的参数 如端口号

程序执行结果如下:
在这里插入图片描述
然后在浏览器中,输入网址:http://127.0.0.1:8000/ ,运行效果如下图所示:
在这里插入图片描述

二、路由

当客户端(例:Web浏览器)把请求发送给 Web 服务器后,Web 服务器再把请求发送给 Flask 程序实例。程序实例需要知道每个 URL 请求运行了哪些代码,所以保存了一个 URL 到 Python 函数的映射关系。处理URL和函数之间关系的程序称为路由。

在 Flask 程序中定义路由的最简便方式,是使用程序实例提供的 app.route 装饰器,把装饰的函数注册为路由。路由映射关系如图所示:
在这里插入图片描述
说明:在 @app.route() 函数中添加 URL 时,URL 有时是变化的。例如,同一作者不同文章的 ID 是变化的,如下:

https://blog.csdn.net/xw1680/article/details/117434720
https://blog.csdn.net/xw1680/article/details/117854388

针对这种情况,可以构造含有动态部分的 URL,也可以在一个函数上附着多个规则。要给 URL 添加变量部分,可以把这些特殊的字段标记为 <变量名> 的形式,它将会作为命名参数传递到函数。如果要对变量名的类型进行限制,则可以用 <变量类型:变量名> 指定一个可选的类型转换器。

【示例2】根据不同的用户名参数输出相应的用户信息,代码如下:

from flask import Flask  # 导入Flask类

app = Flask(__name__)


@app.route("/")
def index():
    return 'Hello Flask!'


@app.route("/user/<username>")
def show_user_info(username):
    # 显示该用户名的用户信息
    return f"用户名是:{username}"


@app.route("/post/<int:post_id>")  # int转换器:接收整数。float:同int,但是接收浮点数。 path:和默认的相似,但也接收斜线。
def show_post(post_id):
    # 根据ID显示文章,ID是整型数据
    return f"ID是:{post_id}"


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

浏览器中测试1:
在这里插入图片描述
浏览器中测试2:
在这里插入图片描述
浏览器中测试3:
在这里插入图片描述
浏览器中测试4:
在这里插入图片描述
【示例3】模拟登录成功后页面跳转至首页的效果,代码如下:

from flask import Flask, url_for, redirect  # 导入Flask类

app = Flask(__name__)


@app.route("/")
def index():
    return 'Hello Flask!'


@app.route("/login")
def login():
    # 模拟登录流程
    flag = True
    # 如果登录成功,跳转到首页
    if flag:
        return redirect(url_for("index"))
    return "登录页面"


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

运行效果如下图所示:
在这里插入图片描述
总结:使用 url_for 函数可以构造 URL,所以它经常结合 redirect() 函数用来跳转到构造的 URL 页面。

# 返回index函数对应的路由 "/"
url_for('index')
# 返回show_post函数对应的路由 "/post/2"
url_for('show_post', post_id=2)
# 返回show_user_info函数对应的路由 "/user/AmoXiang"
url_for('show_user_info', username='AmoXiang')

HTTP(与Web应用会话的协议)有许多不同的访问 URL 方法。默认情况下,路由只回应 GET 请求,但是通过 route() 装饰器传递 methods 参数可以改变这个行为。例如:

@app.route("/login", methods=["GET", "POST"])
def login():
    if request.method == "POST":
        do_the_login()
    else:
        show_the_login_form()

HTTP 方法(也经常被叫作 谓词 )可以告知服务器,客户端想对请求的页面做些什么。常见的方法如下表所示:

方法名说明
GET浏览器告知服务器:只获取页面上的信息并发给我。这是最常用的方法
HEAD浏览器告诉服务器:欲获取信息,但是只关心消息头。
POST浏览器告诉服务器:想在URL上发布新信息。并且,服务器必须确保数据已存储且仅存储一次。这是html表单通常发送数据到服务器的方法
PUT类似POST,但是服务器可能触发了存储过程多次,多次覆盖掉旧值。考虑到传输中连接可能会丢失,在这种情况下浏览器和服务器之间的系统可能安全地第二次接收请求,而不破坏其他东西。因为POST它只触发一次,所以需要使用PUT
DELETE删除给定位置的信息
OPTIONS给客户端提供一个敏捷的途径来弄清这个URL支持哪些HTTP方法。从Flask 0.6开始,实现了自动处理

动态 Web 应用也会需要静态文件,该文件通常是 CSS 和 javascript 文件。默认情况下,只要在包中或是模块的所在目录中创建一个名为 static 的文件夹,在应用中使用 /static 即可访问。例如,Flask_demo 文件夹为应用目录,在 Flask_demo 目录下创建 static 文件夹,目录结构如下图所示:
在这里插入图片描述
给静态文件生成 URL,可以使用特殊的 static 端点名,浏览器中测试如下:
在这里插入图片描述

三、模板

模板是一个包含响应文本的文件,其中包含用占位变量表示的动态部分,其具体值只在请求的上下文中才能知道。使用真实值替换变量,再返回最终得到的响应字符串,这一过程称为渲染。为了渲染模板,Flask 使用了一个名为 Jinja2 的强大模板引擎。

默认情况下,Flask 在程序文件夹中的 templates 子文件夹中寻找模板。Flask 使用 render_template() 函数渲染模板,语法如下:

def render_template(template_name_or_list, **context):

注意:render_template 函数需要从 Flask 包中导入,它的第一个参数是渲染的模板名称,其余参数为模板中变量的值。 例如:

return render_template('user.html',username=name)

如果在视图函数中调用上面的代码,则会渲染 templates 目录下的 user.html 模板文件,并且将模板文件中的 {{username}} 使用 name 的值来替换。

【示例4】渲染首页模板。在 Flask_demo 目录下创建 templates 文件夹,并且在 templates 文件夹下新建 index.html 模板文件,如下图所示:
在这里插入图片描述
index.html 中代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Flask 渲染模板案例演示</title>
</head>
<body>
    <h1>阿莫的Python每日一练</h1>
    <ul id="practice_list">
        <li>{{value1}}</li>
        <li>{{value2}}</li>
        <li>{{value3}}</li>
        <li>{{value4}}</li>
    </ul>
</body>
</html>

templates_demo.py 中代码如下:

from flask import Flask, render_template

app = Flask(__name__)


@app.route('/')
def index():
    value1 = "Python每日一练(20)-用Python制作mini翻译器"
    value2 = "Python每日一练(19)-通过爬虫实现GitHub网页的模拟登录"
    value3 = "Python每日一练(18)-抓取小说目录和全文"
    value4 = "Python每日一练(17)-通过正则表达式快速获取电影的下载地址"
    # value1=value1 关键字参数
    # 左边的value1 ==> 参数名,对应模板中的占位符
    # 右边的value1 ==> 当前作用域中的变量,表示这个参数的值
    return render_template("index.html", value1=value1, value2=value2, value3=value3, value4=value4)


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

运行效果如下图所示:
在这里插入图片描述
Jinja2 能识别所有类型的变量,甚至是一些复杂的类型,例如列表、字典和对象。在模板中使用变量的一些示例如下:

<li>从列表中取一个值:{{value5[2]}}</li>
<li>从列表中取一个带索引的值:{{value5[index]}}</li>
<li>从字典中取一个值:{{my_dict['key']}}</li>
<li>从对象的方法中取一个值:{{obj.method()}}</li>

可以使用过滤器修改变量,过滤器名添加在变量名之后,中间使用竖线分隔。例如,下述模板以首字母大写形式显示变量 name 的值:

<li>Hello, {{name|capitalize}}</li>

Jinja2 提供的部分常用过滤器如下表所示:

名称说明
safe渲染值时不转义
capitalize把值的首字母转换成大写,其他字母转换成小写
lower把值转换成小写形式
upper把值转换成大写形式
title把值中每个单词的首字母都转换成大写
trim把值的首尾空格去掉
striptags渲染之前把值中所有的HTML标签都删掉
default()设置默认值,默认值作为参数传入,别名为d
escape(s)转义HTML文本,别名为e
first (seq)返回序列的第一个元素
last(seq)返回序列的最后一个元素
length(object)返回变量的长度
random(seq)返回序列中的随机元素
max()返回序列中的最大值
min()返回序列中的最小值
unique()返回序列中的不重复的值
wordcount(s)计算单词数量
tojson()将变量值转换为JSON格式
truncate()截断字符串常用于显示文章摘要,length参数设置截断的长度
killwords 参数设置是否截断单词,end参数设置结尾的符号

【示例5】统计文章的长度。在 templates 文件夹下新建 article.html 模板文件,代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>统计文章的长度</title>
</head>
<body>
<p style="color: red">全文共{{content|count_length}}字</p>
<p style="color: blue">全文共{{content | length()}}字</p>
<p>{{content}}</p>
</body>
</html>

templates_demo2.py 中代码如下:

from flask import Flask, render_template

app = Flask(__name__)


# def count_length(arg):  # # 实现一个可以求长度的函数
#     return len(arg)
# 
# 
# app.add_template_filter(count_length, 'count_length')


@app.template_filter()  # 使用装饰器
def count_length(arg):  # 实现一个可以求长度的函数
    return len(arg)


@app.route('/')
def index():
    content = """
    Flask是一个使用Python编写的轻量级Web应用框架,基于Werkzeug WSGI工具箱和Jinja2模板引擎。Flask被称为微框架,
    因为它使用简单的核心,用扩展增加其他功能。Flask没有默认使用的数据库、窗体验证工具等。然而,Flask保留了扩增的弹性,
    可以用Flask扩展加入这些功能,例如:ORM、窗体验证工具、文件上传、各种开放式身份验证技术等等。
    """
    return render_template("article.html", content=content)


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

运行效果如下图所示:
在这里插入图片描述
Jinja2 提供了多种控制结构,可用来改变模板的渲染流程。在模板中使用条件控制语句,代码如下:

{% if user %}
hello, {{user}}!
{% else % }
hello, Paul!
{% endif %}

使用 for 循环在模板中渲染一组元素,代码如下:

<ul>
    {% for comment in comments %}
    <li>{{comment}}</li>
    {% endfor %}
</ul>

Flask 框架有上下文,Jinja2 模板也有上下文。通常情况下,在渲染模板时调用 render_template() 函数向模板中传入变量。此外,还可以使用 set 标签在模板中定义变量,例如:

{% set navigation = [('/', 'home'), ('/about', 'About')] %}

也可以将一部分模板数据定义为变量,使用 setendset 标签声明开始和结束,例如:

{% set navigation %}
<li><a href="/">首页</a></li>
<li><a href="/about">关于我们</a></li>
{% endset %}

Flask 在模板上下文中提供了一些内置全局变量,可以在模板中直接使用,内置全局变量及说明如下表所示:

属性说明
config当前的配置对象
request当前的请求对象,在已激活的请求环境下可用
session当前的会话对象,在已激活的请求环境下可用
g与请求绑定的全局变量,在已激活的请求环境下可用

模板继承类似于 Python 中类的继承。Jinja2 允许定义一个基模板(也称作父模板),把网页上的导航栏、页脚等通用内容放在基模板中,而每一个继承基模板的子模板在被渲染时都会自动包含这些部分。使用这种方式可以避免在多个模板中编写重复的代码。在 Jinja2 中,使用 extends 标签实现子模板对父模板的继承。父模板,代码如下:

{% include '_nav.html' %}
{% block content %}
{% endblock %}
{% include '_footer.html' %}

说明:上述代码中,使用 include 标签引入了 _nav.html 导航栏和 _footer.html 底部信息栏等 html 文件。然后使用 block 标签作为占位符,命名为 content。父模板中的占位符将被子模板中的名为 content 的 block 标签的内容替换。

子模板,代码如下:

{% extends 'base.html' %}
{% block content %}
使用block标签替换父模板中的content内容。
{% endblock %}

在开发过程中,经常需要提示用户当前操作成功或失败的情况。例如,在添加商品信息页面,如果添加成功,应该提示 添加成功 信息,否则提示 添加失败 信息。针对这种需求,Flask 提供了一个非常有用的 flash() 函数,它可以用来 闪现 需要显示给用户的消息。flash() 函数语法格式如下:

flash(message,category)

参数说明:

  1. messag:消息内容。
  2. category:消息类型,用于将不同的消息内容分类处理。

通常在视图函数中调用 flash() 函数,传入消息内容即可 闪现 一条消息。当然,它不是在用户的浏览器弹出一条消息。实际上,使用 flash() 函数发送的消息会存储在 Session 中,需要在模板中使用全局函 get_flashed_ messages() 获取消息列表,并将其显示出来。

说明:通过 flash() 函数发送的消息会存储在 session 对象中,所以需要为程序设置密钥。可以通过 app.secret_key 属性或配置变量 SECRET_KEY 设置。

【示例6】注册错误处理函数自定义错误页面。404.html模板内容代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>404页面</title>
</head>
<body>
<img src="{{url_for('static',filename='images/404.png')}}" alt="404页面">
</body>
</html>

error.py 中的代码如下:

from flask import Flask, render_template

app = Flask(__name__)
# app.secret_key = "amoxiang"  # 设置secret_key


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


@app.errorhandler(404)
def page_not_found(e):
    return render_template('404.html')


if __name__ == '__main__':
    app.run(debug=True)  # 运行程序

运行效果如下图所示:
在这里插入图片描述

以上是关于程序猿哥哥带你快速入门Flask框架的主要内容,如果未能解决你的问题,请参考以下文章

程序猿哥哥带你快速入门 Python GUI设计(tkinter)

燃烧的巨蟒—带你入门Flask网站制作框架

flask-带你快速入门

2 个案例带你迅速入门 Python Flask 框架

一篇博客带你入门Flask

Python 什么是flask框架?快速入门