一、使用路由和视图函数

1.1 路由的概念

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

1.2 定义一个路由

定义一个路由需要使用 app.route 修饰器,把修饰的函数注册为路由。与之配套的是 视图函数,Flask 通过这个视图函数,来处理客户端的请求并返回数据

from flask import Flask

app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello World"

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

这里解释一下上述代码。我们使用 hello() 函数注册为根地址的处理程序,当服务器接收到来自 http://localhost:5000 的网络请求,flask 示例就会查找根目录下的 视图函数 (hello 函数),找到后把返回值给客户端。

1.3 使用 动态路由

我们可以在传递的 url 中指定参数,然后我们在地址栏输入的参数就可以显示到网页当中,只需使用特定的语法就可以实现

  1. 传入动态参数
  2. 传入默认参数

这里补充一点点内容,一个 视图函数可以绑定多个 URL

from flask import Flask

app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello World"

# 在这里我们可以在地址栏中 传入 name 参数,然后在 视图函数中可以接收到这个参数,并把数据显示出来
@app.route("/user", defaults={'name':'Programmer'})
@app.route("/user/<name>")
def user(name):
    return f"<h1>Hello {name} </h1>"

# 指定用户传入的参数类型,这个可以是 int,float,等等其他类型数据
@app.route('/user/<int:num>')
def user1(num):
    return f"<h2>传进来的参数是 {num} </h2>"
	

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

Python Flask 学习笔记 —— 二(路由,视图函数,jinjia2语法)_Flask
Python Flask 学习笔记 —— 二(路由,视图函数,jinjia2语法)_json_02

常见的 URL 处理中的变量转换器
Python Flask 学习笔记 —— 二(路由,视图函数,jinjia2语法)_html_03

1.4 视图函数的响应

参数一:响应内容

Flask’ 实例调用了 视图函数之后,会将其返回值作为响应内容。响应的内容包含简单的字符串,json 数据,xml 数据,html 页面给客户端

参数二:http 状态码

但是 http 协议中一个重要的部分就是 响应状态码。FLask 中默认的状态码都是 200,其实这个我们是可以手动改变的,比如手动改变 404 使访问失效

参数三:header 对象

这里一般不需要设置,但是如果我们想要返回指定格式的数据,比如 html,我们需要在 header 中加上 Content-Type: text/html ,json数据就是 json 还有很多等等

1.4.1 生成重定向的响应

访问该路由时,会跳转到 百度的主页

from flask import Flask,redirect

app = Flask(__name__)

@app.route("/hello")
def hello():
    return redirect('http://www.baidu.com')

@app.route('/hi')
def hi():
    return redirect(url_for('hello')) # 重定向到 /hello

app.run()

1.4.2 返回 JSON 数据

from flask import Flask, make_response
import json

app = Flask(__name__)

# 这种方法不常用
@app.route("/api/json1")
def json1():
    data = {
            "name":"Gelly",
            "age":18
           }
    # 生成指定的响应
    response = make_response(json.dumps(data))
    # 指定返回的数据为 json
    response.mimetype = 'application/json'
    return response
 
# 使用 flask 提供的 jsonfiy 函数实现 json序列化
@app.route("/api/json2")
def json2():
    data = {
            "name":"Gelly",
            "age":18
           }
    return jsonify(data)

if __name__ == '__main__':
    app.run(host="127.0.0.1",debug=True,port=5000)

返回结果
Python Flask 学习笔记 —— 二(路由,视图函数,jinjia2语法)_Python_04

1.5 自定义错误页面

像常规路由一样,flask 允许程序基于模板自定义错误页面,最常用的状态码有另个 404,500,下面是使用示例

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

@app.errorhandler(500)
def internal_server_error(e):
    return render_template('500.html'),500

当我们访问一个不存在的页面时,就会提示我们页面不存在了
Python Flask 学习笔记 —— 二(路由,视图函数,jinjia2语法)_html_05

1.6 路由请求方法监听(补充更新)

路由默认只监听 GET 方法,如果需要监听其他的请求方法,我们需要在 属性 methods 中指定

我们只需要在装饰器中增加一个 methods 参数,就可以实现其它的请求

如果我们需要根据不同的请求方式来返回不同的数据,就可以使用 request.method 方法来实现

from flask import Flask,request

app = Flask(__name__)
 
@app.route("/", methods=['POST','GET'])
def hello():
    # 如果是 post 请求就做如下参数
    # 指定请求,返回不同的数据
    if request.method == 'POST':
		return "Hello"
	else:
		return 'Hello World'

app.run()
二、模板语法

2.1 Jinjia2 模板初体验

首先在 flask 项目的根目录创建一个 templates 的目录,然后写两个简单的 html 文件,分别是 index.html 和 user.html

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>我是第一个页面</title>
</head>
<body>
    <h1>Hello World</h1>
</body>
</html>

user.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>欢迎你 {{name}}</title>
</head>
<body>
	<!-- 这里我就是用了 Jinjia 2 的模板语法 -->
    <h1>欢迎你,{{name}}</h1>
</body>
</html>

然后修改视图函数,使用 render_template 会使 flask 程序目录中的 templates 子文件中搜寻对应的文件。

render_template 第一个参数对应的是模板文件名,随后的参数都是键值对,表示模板中对应的真实的值

from flask import render_template

@app.route("/")
def hello():
    # 渲染模板
    return render_template('index.html')

# 动态路由
@app.route("/user/<name>")
def user(name):
    return render_template('user.html', name=name) # name 第一个参数对应模板中的 {{name}} ,作为占位的租用,第二个参数则对应占位符的值

显示效果(根页面)
Python Flask 学习笔记 —— 二(路由,视图函数,jinjia2语法)_html_06
模板页面
Python Flask 学习笔记 —— 二(路由,视图函数,jinjia2语法)_json_07

2.2 变量

上面的示例中我使用了 {{ name }} 结构表示一个变量,它属于一种特殊的占位符,它会告诉模板这个位置的值从渲染模板时使用的数据获取

Jinjia2 可以识别所有类型的变量,甚至是一些复杂的数据结构,比如列表,字典和对象。下面一些示例使用

视图函数的内容渲染:

render_template 第一个参数对应的是模板文件名,随后的参数都是键值对,表示模板中对应的真实的值

@app.route("/test")
def test():
    isTrue = True
    data = {
        "name": "小黑",
        "age": 18
    }
    ls = [1,2,3]
    return render_template('index.html',isTrue=isTrue,data=data,ls=ls)

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>我是第一个页面</title>
</head>
<body>
    <h1>Hello World</h1>

    <!--test 示例-->
    显示对象内容 {{data}}
    <br>
    显示对象中的姓名{{data.name}}
    <br>
    显示对象中的年龄 {{data.age}}
    <br>
    显示布尔值 {{isTrue}}    <br>
    显示列表 {{ls}}  <br>
    显示列表中的第一个数据 {{ls[0]}}
</body>
</html>

Python Flask 学习笔记 —— 二(路由,视图函数,jinjia2语法)_Flask_08

2.3 使用过滤器

在 Jinjia2 中可以使用过滤器修改变量

基本格式:竖线 + 关键字的形式显示

<!-- 首字母大写 -->
{{ name | capitalize}}

2.3.1 常见过滤器

Python Flask 学习笔记 —— 二(路由,视图函数,jinjia2语法)_Flask_09

2.3.2 使用过滤器

@app.route("/test")
def test():
    isTrue = True
    data = {
        "name": "gorit smith",
        "age": 18
    }
    ls = [1,2,3]
    return render_template('index.html',isTrue=isTrue,data=data,ls=ls)
    <p>使用过滤器:首字母大写,其他小写:{{data.name | capitalize}}</p>
    <p>upper: 把值转换为 大写形式{{data.name | upper}}</p>

Python Flask 学习笔记 —— 二(路由,视图函数,jinjia2语法)_Python_10

2.4 控制结构

从下面一段代码可以看出,在 jinjia2 中我们一样可以使用 Python 的语法来编写,只不过在条件判断中要加上一个判断的结尾,来告诉 flask 程序,这个网页模板中的判断条件结束了。

<!-- 访问对象可以使用 . 和 字典方式访问-->
    jinjia2 数据被隱藏了{#Jinjia2#}
    <h2>if 判断使用</h2>
    <!-- 显示数据 ,显示 html 标签-->
                        <!--    -->
        {% if data.age < 18 %}
            {{data.name}}
        {% elif data.age == 18 %}
             do Something
                 {% else %}
            {{data.age}}
        <a href=""></a>
        {% endif %}

2.5 循环语法

Jiajia2 模板中的循环语法是和 Python 中的 for 循环基本相似

    <h2>for in 循环</h2>
        {% for foo in [1,2,3,4,5]%}
            {{foo}}
        <!--div 标签会显示三次-->
        <div>111</div>
        {% endfor %}
    <h4>for 遍历字典</h4>
        {% for key,value in data.items() %}
            {{key}} {{value}}
        <br>
        <!-- div 标签会显示三次-->
        <div>111</div>
        {% endfor %}

2.6 访问静态文件

静态文件有很多,比如一个 html 文档, css文件, js 文件,图片等等都属于静态文件,在 Python Flask 当中,如果我们要是静态文件能够访问,就需要在根目录加上 一个 static 目录,然后使用 flask 中的 url_for() 函数指定静态文件的路径即可,下面来看一看具体的示例

我先定义类一个名为 img 的视图函数,让它加载 watch.html

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

让我在根目录里创建了一个 static 文件,专门存放一些静态文件
Python Flask 学习笔记 —— 二(路由,视图函数,jinjia2语法)_Flask_11
接下来是编写 watch.html 文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
	<!-- 静态地址的访问使用 url_for 指定第一个参数,表示为静态文件,第二个参数为 filename,参数值是静态文件在 static 目录中的位置 -->
    <p>显示静态文件 <img src="{{ url_for('static', filename='./my_blog.png') }}" width="50" ></p>
</body>
</html>

然后我们运行一下 flask,然后在根目录加上 /watch 就可以看到静态文件了

 

2.7 前端页面外联跳转

当我们使用 Flask 访问了一个不存在的页面时,Flask 就给我们返回一个 404 的页面,然后我们进入这个页面后,单击返回,就可以返回到主页,这里要怎么做呢?

其实很简单,我们可以使用 url_for(‘视图函数的名称就可以解决啦’)

<a href="{{url_for('web.index') }}">惩罚博主</a>

解释一下,我为什么前面要加一个 web, 因为我定义了一个名为 web 的 blueprint,所以需要加上 web 来解决跳转到主页的问题。