PythonWeb开发应用

目录

1.Flask

2.安装Flask

3.Flask程序

(1)Flask程序的运行

(2)FLASK_APP和FLASK_DEBUG

(3)程序的基本结构

Flask类

开发服务器

路由与视图

4.路由

(1)注册路由

route()

add_url_rule()

(2)URL传递参数

变量传递

converter

5.请求处理

GET

POST

上下文

Flask的请求上下文

request

session

Flask的应用上下文

current_app对象

g对象

6.响应处理

(1)响应报文

(2)Response类

(3)make_response()函数

7.URL反向解析

8.页面重定向

9.模块

(1)创建模块

(2)模块基础语法

(3)过滤器

内置过滤器

(4)选择结构

(5)循环结构

10.消息闪现

(1)flash()函数

(2)get_flashed_messages()函数

11.静态文件的加载

(1)在模块中引用图片文件

(2)在模块中引用css文件


1.Flask

Flask提供了一组工具和库,帮助开发者快速构建Web应用程序。它使用Python的装饰器语法来定义路由和视图函数,使用简洁的方式处理HTTP请求和响应。

•Flask不强制使用特定的数据库或模板引擎,而是允许开发者根据需求选择适合的工具。

•Flask自带开发服务器,无须安装比如Tomcat、JBoss、Apache等网络服务器。

•基于Flask开发的程序可开启调试状态(app.debug = True),出现异常时,Flask程序会同时向启动Python程序的控制台和HTTP客户端发送错误信息

Flask完全基于Unicode编码格式,对制作非纯ASCII字符集的网站而言非常方便。HTTP协议要求每次传输时需要在请求头显式指定编码格式,Flask程序默认会为请求头指定UTF-8编码,使开发者无须担心编码问题。

:Flask只保留Web开发的核心功能,不包括用户认证、表单验证、邮件发送等功能,但可在Fask官网找到相应的扩展包对网站进行个性化定制。

Flask默认依赖两个外部库:Werkzeug WSGI工具包和Jinja2模板引擎

WSGI:

WSGI(Web服务器网关接口)是为Python语言定义的Web服务器和Web应用程序或框架之间的一种简单而通用的接口,它制定了一套通信标准,保证Web服务器可以跟Web应用程序之间相互通信。Flask程序完全兼容WSGI,它能够运行到任何Web服务器。

Werkzeug WSGI:

Werkzeug是一个WSGI工具包,他可以作为一个Web框架的底层库。 werkzeug 不是一个web服务器,也不是一个web框架,而是一个工具包,它封装好了很多 Web 框架的东西,例如 Request,Response 等等。

Jinja2:

Jinja2模板,模板简单来说就是一个其中包含 占位变量 表示 动态 部分的文件,模板文件在经过动态赋值后,返回给用户。

- JinJa2模板引擎将HTML页面和应用程序联系起来。

- JinJa2模板引擎由Django模板引擎发展而来,但比Django模板引擎更高效。

- Jinja2模板引擎使用配制的语义系统,它不仅提供了灵活的模板继承技术,还可以自动防止(XSS)跨站攻击。

2.安装Flask

pip install flask

安装Flask会对应6个依赖包

依赖包说明
Jinja2模板渲染引擎
MarkupSafeHTML字符转义工具
WerkzeugWSGI工具集,它封装了Web框架中的很多内容,包含请求、响应、WSGI开发服务器、调试器和重载器
click命令行工具
colorama命令行彩色显示工具
itsdangerous提供各种加密签名功能

 requirements.txt

不同的Flask项目可能会依赖不同的虚拟环境,若要在新计算机中运行项目,就需要重复为该项目配置一套相同的虚拟环境,为了区分和记录每个项目的依赖包及其版本,以便在新计算机中复现项目的虚拟环境,我们可以通过一个requirements.txt文件记录项目的所有依赖包及其版本号,以便在新计算机中实现一键安装的效果。

需要说明的是,requirements.txt文件的名称是开发者之间约定俗成的,也可以进行重新命名。

通过pip命名将环境依赖的扩展包及其版本号记录到requirements.txt文件中

pip freeze > requirements.txt

在另一台计算机中通过运行以下pip命令将记录的依赖包及其版本号安装相应版本的依赖包

pip install -r requirements.txt

3.Flask程序

(1)Flask程序的运行
# 新建一个名称为app.py的文件
from flask import Flask   #导入Flask类
app = Flask(__name__) # 实例化Flask类
@app.route("/") # 定义视图函数,并为该函数注册路由
def hello_flask():
    return '<p>Hello, Flask!</p>'
if __name__ == '__main__':
    app.run() # 启动开发服务器

注:这里可以直接运行程序代码,也可以在命令行窗口执行flask run命令启动程序(Ctrl + C可以退出)

(2)FLASK_APPFLASK_DEBUG

FLASK_APP

执行flask run命令时,Flask会使用内置的开发服务器运行程序。默认会假设程序存储在名为app.py或者wsgi.py的文件中。如果使用其他名称,则要设置系统环境变量FLASK_APP,告诉Flask要启动的对应程序。

- Linux系统:export FLASK_APP=hello.py

- Windows CMD:set FLASK_APP=hello.py

- Windows PowerShell: $env:FLASK_APP ="hello.py"

FLASK_DEBUG

FLASK_DEBUG用于开启调试模式(debug mode)。调试模式开启后,当程序出错,浏览器页面上会显示错误信息;代码出现变动后,程序会自动重载。

> set FLASK_DEBUG=1

> flask run

或者

>flask run --debug

(3)程序的基本结构

Hello Flask程序包含3个比较重要的部分,分别是Flask类、开发服务器、路由与视图。

Flask类

Flask类是flask包中的核心类,该类中封装了很多与Flask程序相关的方法,通过这些方法可以轻松地对Flask程序进行相应的操作。所有的Flask程序中必须要创建一个Flask类的对象。

app=Flask(__name__)

 必须参数__name__是Flask中一个特殊的变量,用于保存程序主模块或者包的名称。可选参数有以下:

•static_folder:用于指定存放静态文件的文件夹名称,默认值为static

•static_url_path:用于指定前端访问静态文件的路径,默认值为static_folder的名称。

•template_folder:用于指定存放模板文件的文件夹名称,默认为应用程序根路径下的templates文件夹。

开发服务器

Flask的依赖包Werkzeug提供了一个简易的开发服务器

使用开发服务器有两种方式,一种为命令行启动,另一种是通过代码方式,即调用Flask类的对象的run()方法

app.run() 

•host:运行当前程序的主机名称,默认值为'127.0.0.1'或'localhost'。

•port:运行当前程序的主机对应的端口号,默认值为5000。

•debug:是否启用调试模式,默认值为False。

路由与视图

- 路由是一种目前主流的Web框架中应用的技术,用于帮助用户直接根据URL访问某个页面,而无须再从主页导航到这个页面。当初始化Flask类对象时,会注册程序中所有的URL规则,一旦用户在浏览器发送访问某个页面的URL请求后,服务器便会将该URL请求交给Flask程序,这时Flask程序会根据URL规则找到与之关联的视图。

- 在Flask中,视图是Python函数或Python类,用于对浏览器发送的请求进行处理,并返回响应内容给Web服务器。视图返回的响应内容既可以是一个包含HTML代码的字符串,也可以表单等。

在Hello Flask程序中,定义视图函数及URL规则代码如下:

@app.route("/")

def hello_flask():

    return '<p>Hello, Flask!</p>'

4.路由

(1)注册路由

在Flask程序中,浏览器通过URL发送HTTP请求给Web服务器,Web服务器再将HTTP请求转发给Flask程序。Flask程序接收到HTTP请求后需要知道Flask程序中哪部分代码对这个请求进行处理。为此,Flask程序保存了一个URL与视图函数或类的映射关系,建立映射关系的过程称为注册路由

在Flask中,注册路由一般分为两种方式,一种方式是通过route()方法进行注册,另一种方式是通过add_url_rule()方法进行注册。

route()

route()是Flask类提供的方法,该方法用于将视图函数与特定的URL建立关联,当通过浏览器访问URL时程序内部自动调用与之关联的视图函数。

route(rule, methods, **options)

•rule:必选参数,表示URL规则字符串,该字符串必须以“/”开始。

•methods:可选参数,表示HTTP请求方法。

•**options:可选参数,表示传递给底层werkzeug.routing.Rule对象的额外选项。

#route()方法需要以装饰器的形式写在视图函数的上方。
from flask import Flask
app = Flask(__name__)
@app.route('/index') # 通过route()方法注册路由,URL规则为/index
def index():
    return f'<h1>这是首页!</h1>'
if __name__ == '__main__':
    app.run()

注:若URL规则字符串以“/”结尾,但用户访问URL时并没有在URL末尾附加“/”,则会自动重定向到附加了“/”的页面;若URL规则字符串的末尾没有附加“/”,但用户通过URL访问页面时在URL末尾附加了“/”,则会出现404页面。 

结果:

add_url_rule()

add_url_rule()也是Flask类提供的方法,一般需要传递URL和URL关联的函数名。

add_url_rule(rule, endpoint=None, view_func=None,provide_automatic_options=None, **options)

•rule:必选参数,表示URL规则字符串,必须以’/’开始。

•endpoint:可选参数,表示端点名称。

•view_func:可选参数,表示与端点关联的视图函数名,只写函数名,不需要加括号。

•methods:可选参数,表示定义的HTTP请求方法。

•**options:可选参数,表示传递给底层werkzeug.routing.Rule对象的额外选项。

#add_url_rule()方法注册路由,使视图函数与URL建立关联

from flask import Flask
app = Flask(__name__)
def index_new():
    return f'<h1>这是首页1!</h1>'

# 通过add_url_rule()方法注册路由
app.add_url_rule(rule='/index1', view_func=index_new) 
if __name__ == '__main__':
    app.run()

 结果:

注:route()方法内部其实调用了add_url_rule()方法,route()方法的用法更简洁,无需传入与URL规则关联的视图函数名。

在Flask程序中,一个视图函数也可以绑定多个URL,当浏览器访问这些URL时会触发Flask程序中的同一个视图函数,也就是说在浏览器中展示的效果相同。

@app.route('/homepage')

@app.route('/index')

def index():

    return f'<h1>这是首页!</h1>

(2)URL传递参数
变量传递

当调用route()或add_url_rule()方法注册路由时,可以在URL规则字符串中加入尖括号包裹的变量,用于标记URL中动态变化部分的内容,之后将该变量作为参数传递给视图函数

from flask import Flask
app = Flask(__name__)
@app.route('/<page>')   # URL规则字符串中加入尖括号变量page
def page_num(page):     # 将page参数传递给视图函数
    return f'当前为第{page}页'
if __name__ == '__main__':
    app.run()

结果:

converter

当URL向视图函数传递参数时,如果需要限定参数的类型,那么可以通过转换器指定参数的类型。

<converter:variable_name>

 converter表示转换器,它支持两种类型的转换器,分别是内置转换器自定义转换器

•内置转换器

如果为参数明确指定了转换器,那么URL中传递的参数必须符合转换器要求的数据类型。

转换器说明
string默认值,匹配非空字符串,但不包含“/”
any匹配给定的一系列值中的某一个元素
int匹配整型
float匹配浮点型
path与string类似,匹配非空字符串,但允许字符串中包含“/”
uuid匹配UUID字符串
from flask import Flask
app = Flask(__name__)
@app.route('/<int:page>')   # page显式指定为int
def page_num(page):     # 将page参数传递给视图函数
    return f'当前为第{page}页'
if __name__ == '__main__':
    app.run()

page参数一定要为ing,如果不是,就会出现“Not Found”参数

​​​​​​​

•自定义转换器

来看一个例子,to_python() 方法将从 URL 中获取的字符串类型的值转换为整型,并加上100。

from flask import Flask, url_for
from werkzeug.routing import BaseConverter

# 定义自定义转换器类
class MyIntConverter(BaseConverter):
    def to_python(self, value):
        try:
            return int(value) + 100
        except ValueError:
            pass

# 创建Flask应用程序
app = Flask(__name__)

# 注册自定义转换器
app.url_map.converters['myint'] = MyIntConverter

# 定义路由和视图函数
@app.route('/page/<myint:page>')
def show_page(page):
    return f'当前为第{page}页'

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

结果:

5.请求处理

Flask程序可以在使用装饰器route()或add_url_rule()方法注册路由时传入参数methods来指定使用的请求方法,该参数会以列表形式接收一种或多种请求方法。在HTTP规范中,定义了一组常用的请求方法:GET和POST

注:在Flask程序的视图函数中,默认的请求方式为GET

GET

•通常用于请求服务器上的资源,例如网页、图片、视频等。

•通过URL的查询字符串(query string)传递参数,参数会显示在URL中,可以被书签收藏,也可以被缓存。

•数据限制:由于参数是附加在URL上的,所以传输的数据量有限制,一般不能超过几千个字符。

•安全性:GET请求的参数在URL中可见,因此不适合传输敏感信息,如密码等。

#在视图函数login()上方通过装饰器route()注册路由,并显式指定请求方法为GET

@app.route('/login', methods=['GET'])
def login():
    pass
POST

•通常用于向服务器提交数据,例如表单提交、上传文件等。

•通过HTTP请求的消息体传递参数,参数不会显示在URL中,对于大量数据或敏感信息更为安全。

•数据限制:由于参数在消息体中,所以传输的数据量相对较大,一般没有特定的限制。

•安全性:POST请求相对于GET请求更为安全,适合传输敏感信息。

#在视图函数login()上方通过装饰器route()注册路由,并显式指定请求方法为GET和POST。

@app.route('/login', methods=['GET', 'POST'])
def login():
    pass

补充:HTTP的九种请求方法:

1 GET 请求指定的页面信息,并返回实体主体。

2 HEAD 类似于 GET 请求,只不过返回的响应中没有具体的内容,用于获取报头

3 POST 向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST 请求可能会导致新的资源的建立和 / 或已有资源的修改。

4 PUT 从客户端向服务器传送的数据取代指定的文档的内容。

5 DELETE 请求服务器删除指定的页面。

6 CONNECT HTTP/1.1 协议中预留给能够将连接改为管道方式的代理服务器。

7 OPTIONS 允许客户端查看服务器的性能。

8 TRACE 回显服务器收到的请求,主要用于测试或诊断。

9 PATCH 是对 PUT 方法的补充,用来对已知资源进行局部更新 。

最常用的还是 GET , POST

在Flask2.0及其之后的版本提供了指定部分请求方式的便捷函数,这些函数与请求方法的名称相同,且都是小写形式的。

•get():route()传递methods=["GET"]的快捷函数。

•post():route()传递methods=["POST"]的快捷函数。

•put():route()传递methods=["PUT"]的快捷函数。

•delete():route()传递methods=["DELETE"]的快捷函数。

•patch():route()传递methods=["PATCH"]的快捷函数。

@app.post('/login')
def login():
    pass

上下文

Flask使用上下文临时保存程序运行过程中的一些信息。Flask中有两种上下文,分别是请求上下文和应用上下文,其中应用上下文是随着请求上下文产生而产生,随着请求上下文销毁而销毁。

Flask的请求上下文

Flask的请求上下文包括request对象和session对象,其中request对象封装了请求信息session对象用于记录请求会话中的用户信息。

request

- request对象中提供了用于处理请求信息的常用属性

属性说明
args获取URL中的请求参数
methods获取请求的HTTP方法
cookies获取包含Cookie名称和值的字典对象 
data获取包含字符串形式的请求数据
form获取解析后的表单数据
values一个包含form和args全部内容的CombineMultiDict
headers获取首部字段
user_agent获取浏览器标识信息

- request对象中提供了用于处理请求信息的常用方法

方法说明
close()关闭当前请求
get_data()获取请求中的数据
get_json()作为JSON解析并返回数据
make_form_data_parse()创建表单数据解析器
session

- session对象提供了很多获取Cookie信息的方法

方法说明
get(key)通过传入的key值,获取Cookie中对应的value值
pop(key)通过传入的key值,删除Cookie中对应的value值
items()将Cookie中的值以“key:value”形式返回
values()获取Cookie中所有的value值
clear()清空当前站点Cookie中的内容
keys()获取Cookie中所有的key值
update()

接收一个字典,根据接收的字典更新或添加到Cookie中

Flask的应用上下文

Flask的应用上下文包括current_app对象和g对象,其中current_app对象表示当前激活的Flask应用程序实例;g对象表示程序的一个全局临时变量,我们可以通过g对象在一次请求调用的多个函数间传递一些数据,每次请求都会重设这个变量。

current_app对象

当Flask程序无法导入程序实例或程序中有多个程序实例时,为了能够快速区分当前请求的程序实例,此时可以使用current_app对象。

from flask import Flask, current_app  # 导入current_app对象
app = Flask(__name__)
app.secret_key = 'Your_seccret_key&^52@!'
@app.route('/')
def index():
    return f'{current_app.secret_key}'# 通过current_app对象获取密钥
if __name__ == '__main__':
    app.run()
g对象

g对象存储了一次请求的所有用户信息,例如,用户的登录信息、数据库的连接信息等,在同一个请求中,如果后续的代码中需要用户登录信息或数据库连接信息都可以通过g对象获取。当请求完成之后,g对象便会销毁;当发送一个新的请求时,g对象也会随之生成。

#使用g对象模拟获取当前用户信息
from flask import Flask, g
app = Flask(__name__)
@app.route('/')
def get_user():
    user_id = '001'           	# 设置用户id
    user_name = 'flask'    	# 设置用户名称
    g.user_id = user_id      # 将用户id保存到g对象中
    g.user_name = user_name # 将用户名称保存到g对象中
    result = db_query()
    return f'{result}'
def db_query():
    user_id = g.user_id    # 使用g对象获取用户id
    user_name = g.user_name  # 使用g对象获取用户名称
    return f'{user_id}:{user_name}'

结果:

6.响应处理

(1)响应报文

在Flask程序中,浏览器发出的请求会触发相应的视图函数,并将视图函数的返回值作为响应体,之后生成完整的响应内容,即响应报文。响应报文主要由4个部分组成,分别是状态行、响应报头、空行以及响应体。

状态行(Status Line):状态行是响应报文的第一行,用于表示响应的状态和版本。它包含了HTTP版本号、状态码和对应的状态信息。例如:HTTP/1.1 200 OK。这里的 "200" 是成功的状态码,表示请求已成功处理。

响应报头(Response Headers):响应报头位于状态行之后,用于传递关于响应的附加信息。它包含了多个键值对,每个键值对由一个字段名和一个字段值组成,中间用冒号分隔。

响应报头有很多内容,通用报头、请求报头、响应报头、实体报头等

常见的响应报头:

Location:用于重定向接受者到一个新的位置,常用在更换域名的时候

Server:包含可服务器用来处理请求的系统信息,与User-Agent请求报头是相对应的

空行(Blank Line):空行是状态行和响应报头之后的一行,用于分隔响应报头和响应体。它实际上是一个空的换行符。

响应体(Response Body):响应体位于空行之后,用于存储服务器返回给客户端的实际数据。它可以是HTML文档、JSON数据、图片、文件等各种形式的数据。响应体的内容取决于服务器处理请求后返回的数据。

(2)Response类

Response类封装了响应报文的相关信息。如果希望在Flask程序中主动生成响应,一般可以通过Response类的构造方法或make_response()函数实现。

Response(response, status, headers, mimetype, content_type, direct_passthrough)

•response:可选参数,表示视图函数返回的响应体。

•status:可选参数,表示响应状态码。

•headers:可选参数,表示响应报头。

•mimetype:可选参数,表示响应体的MIME类型。

•content_type:可选参数,表示响应体的类型。 

from flask import Flask, Response
app = Flask(__name__)
@app.route('/index')
def index():
    # 使用Response类的构造方法生成响应对象,设置状态码为201,响应类型为text/html
    resp = Response(response='Python&Flask',status=201,                          content_type='text/html;charset=utf-8')
    return resp 
if __name__ == '__main__':
    app.run()

结果: 

(3)make_response()函数

make_response()函数也用于生成响应,它可以接收str、bytes、dict和tuple共4种类型的参数,当参数的类型为tuple时,参数的值可以为(body, status, headers) 、(body, status)或 (body, headers)任意一种形式,其中body表示响应体,status表示状态码,headers表示响应报头,另外header的值可以是一个字典或(key,value)形式的元组。

from flask import Flask, make_response
app = Flask(__name__)
@app.route('/index')
def index():
    res = make_response('Python&Flask123',201,
                            {'content-type':' text/html;charset=utf-8'})
    return res
if __name__ == '__main__':
    app.run()

结果:

7.URL反向解析

URL反向解析(URL Reverse Resolution)是指根据视图函数名称和参数生成对应的URL。在Web应用中,通常会定义一些路由(URL规则)来映射到不同的视图函数,当需要生成特定的URL时,可以使用URL反向解析功能。

URL反向解析的作用:

避免硬编码(硬编码就是直接把URL全名写上去):使用反向解析可以避免在代码中硬编码URL。硬编码的URL在修改时容易出错,并且不利于代码重用和维护。

如果应用中的URL规则发生变化只需要修改路由配置,而不需要在所有使用该URL的地方手动修改URL字符串。

通过反向解析,可以根据视图函数名称和参数生成对应的URL链接。这样,在模板中或者其他地方需要生成URL时,就可以直接调用反向解析函数生成相应的URL,而不需要手动拼接URL字符串。

flask.url_for模块中提供了URL反向解析的函数url_for(),该函数可以根据视图函数的名称获取对应的URL。

url_for(endpoint,values,_external,_scheme,_anchor,_method,**values)

•endpoint:必选参数,表示反向解析的端点(用于标记一个视图函数以及对应的URL规则)名称,默认值为视图函数名。

•values:可选参数,表示URL地址传递的参数。

•_external:可选参数,表示是否供程序外部使用,默认值为False,若为True,则返回绝对URL地址,例如,http://127.0.0.1:5000/hello/flask。

from flask import Flask, url_for
app = Flask(__name__)
@app.route('/hello/flask')
def greet():
    return f"{url_for('greet')}"   # 反向解析视图函数greet()对应的URL 
if __name__ == '__main__':
    app.run()

结果:

若URL规则中包含要传递的参数,则调用url_for()函数时需要将该参数以关键字参数形式传递:

from flask import Flask, url_for
app = Flask(__name__)
@app.route('/hello/<name>')
def greet(name):
    return f"{url_for('greet',name=name)}"   
if __name__ == '__main__':
    app.run()

结果:

使用url_for()函数反向解析URL时,除了传递URL规则中的参数以外,还可以传递任何额外参数给URL地址的参数

from flask import Flask, url_for
app = Flask(__name__)
@app.route('/hello/<name>')
def greet(name):
    # 将age=20添加到URL地址中
    return f"{url_for('greet',name=name, age=20)}"  
if __name__ == '__main__':
    app.run()

结果:

8.页面重定向

页面重定向在Web程序中非常普遍,例如,当用户在电商网站购买商品时,电商网站若检测到用户还未曾登录,则会将当前页面重定向到登录页面。在Flask程序中,页面重定向功能可以通过redirect()函数实现。

redirect(location, code=302, Response=None)

•location:必选参数,表示重定向的URL地址。

•code:可选参数,表示重定向状态码,默认状态码为302。

•Response:可选参数,表示实例化响应时使用的Response类,若未指定默认使用的响应类为werkzeug.wrappers.Response。

 当用户首次访问欢迎页面时,若session中还没有记录过这个用户名,则会将欢迎页面重定向到登录页面;当用户在登录页面输入用户名登录后,会将登录页面重定向到欢迎页面。

from flask import Flask, url_for, request, redirect, session
app = Flask(__name__)
app.secret_key = 'Your_secret_key&^52@!'
@app.route('/index')
def index():
    if 'username' in session:
        return f'你好:{session.get("username")}'  #返回欢迎信息
    return redirect(url_for("login"))    # 页面重定向到登录页面
....

9.模块

在一般的 Web 程序里,访问一个地址通常会返回一个包含各类信息的 HTML 页面。因为我们的程序是动态的,页面中的某些信息需要根据不同的情况来进行调整,比如对登录和未登录用户显示不同的信息,所以页面需要在用户访问时根据程序逻辑动态生成。

我们把包含变量和运算逻辑的 HTML 或其他格式的文本叫做模板,执行这些变量替换和逻辑计算工作的过程被称为渲染,这个工作由模板渲染引擎——Jinja2 来完成。

- Jinja2除了允许在模板中使用变量之外,还允许在模板中使用过滤器、选择结构、控制结构等,以多种方式控制模板的输出。

- Flask已经自动安装了Jinja2,我们在Flask程序中可以直接使用Jinja2。

(1)创建模块

- 创建模板其实就是创建HTML文件。为了保证Flask程序能够加载到模板文件,我们需要在项目的根目录下新建一个templates文件夹,之后将程序中用到的所有模板文件存放到该文件夹中。

- templates是Flask预先定义好的模板文件夹名称,如果希望使用其他的文件夹名称,则可以在通过代码创建Flask类对象时为template_folder参数传入其他的文件夹名称。

为了使用Jinja2模板引擎渲染模板,flask库中提供了render_template()函数。

render_template(template_name_or_list, **context)

•template_name_or_list:必选参数,表示要加载的模板名称。

•**context:可选参数,表示向模板文件传递的参数,以关键字参数的形式进行传递。注意,关键字参数的名称必须与模板文件中的变量名称保持一致。

在项目根目录下新建templates文件夹,在该文件夹下创建模板文件index.html,并在index.html文件中编写HTML代码。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
</head>
<body>
    {#一级标题#}
    <h1>Hello Flask!</h1>
</body>
</html>

在项目中再创建一个app.py文件,并在该文件中先定义一个视图函数, 再在视图函数中渲染模板文件index.html。

from flask import Flask, render_template  # 导入render_template
app = Flask(__name__)
@app.route('/index')
def index():
    return render_template('index.html')  # 渲染模板文件index.html
if __name__ == '__main__':
    app.run()

结果:

​​​​​​​

(2)模块基础语法

在模板里,需要添加特定的定界符将 Jinja2 语句和变量标记出来,下面是三种常用的定界符:

{{ ... }} 用来标记变量。

{% ... %} 用来标记语句,比如 if 语句,for 语句等。

{# ... #} 用来写注释。

 {{ ... }}

​​​​​​​- 模板变量是一种特殊的占位符,它用于标识模板中会动态变化的数据,当模板被渲染时,模板引擎将模板中的变量替换为由视图函数传递的真实数据。

{{variable}}

 - 上述格式中,variable表示模板变量的名称变量名称应与视图函数中传递的关键字参数的名称相同。模板变量的命名规则与Python变量的命名规则相同。

Jinja2能够识别所有类型的变量,例如,列表、字典和对象等。

{{ info[3] }}                  # info是列表,获取列表中索引为3的数据

{{ info[username] }}    # info是字典,获取字典中键为username的数据

{{ info.items() }}          # info是对象,获取对象调用items()方法返回的数据

在app.py文件的视图函数index()中定义一个变量,之后将该变量传入render_template()函数中。

@app.route('/index')
def index():
    name = 'World'   
    return render_template('index.html', name=name) 

#在index文件中通过{{}}传入该变量
<!DOCTYPE html>
<html>
  <head>
    <title>Index Page</title>
  </head>
  <body>
    <h1>Hello, {{ name }}!</h1>
  </body>
</html>

{% ... %}

{% for hobby in hobbies %}

        <li>{{ hobby }}</li>

{% endfor %}

举例:

<!DOCTYPE html>
<html>
<head>
    <title>{{ title }}</title>
</head>
<body>
    <h1>{{ greeting }}, {{ name }}!</h1>
    {% if age >= 18 %}
        <p>You are an adult.</p>
    {% else %}
        <p>You are a minor.</p>
    {% endif %}
    <ul>
    {% for hobby in hobbies %}
        <li>{{ hobby }}</li>
    {% endfor %}
    </ul>
    {# This is a comment. #}
</body>
</html>

(3)过滤器

在Jinja2中,过滤器是用于修改或过滤模板变量值的特殊函数,使用过滤器可以获取更精确的数据。

{{ variable|filter(parameter) }}

variable表示变量的名称,filter(parameter)表示使用的过滤器,其中parameter表示传递给过滤器的参数。如果没有任何参数传给过滤器,则括号可以省略。一个模板变量可以使用多个过滤器,多个过滤器之间使用竖线分隔

内置过滤器

Jinja2提供了许多内置过滤器,也可自定义过滤器,常用的内置过滤器如下:

过滤器说明
abs()返回给定参数的绝对值
random()返回给定列表中的一个随机元素
safe()将变量值标记为安全,保证渲染时不进行转义
tojson()将给定参数序列化为JSON字符串
escape()会将<、>等特殊符号转义成HTML中的符号,使其成为普通字符串,避免渲染
length()返回变量值的长度
sort()对变量保存的数据进行排序,该函数内部调用的是Python的sorted()函数

Jinja2字段

字段说明
join()使用指定符号将字符串中的字符进行拼接,默认符号为空字符串
int()将值转换为整数,如果转换不起作用,返回0
float()将值转换为浮点数,如果转换不起作用,返回0.0
capitalize()将变量值的首字母改为大写字母,其余字母改为小写字母
trim()清除变量值前后的空格
upper()将变量值转换为大写字母

举例:

join()

{% set numbers = [1, 2, 3, 4, 5] %}
{{ numbers|join('-') }}

结果:1-2-3-4-5

int
{% set number_str = "123" %}

{% set number_int = number_str|int %}

在app.py文件中,定义视图函数use_of_filters()以及触发该函数的URL规则/filters,在视图函数use_of_filters()中向模板传递不同类型的数据。

@app.route('/filters')
def use_of_filters():
    num = -2.3
    li = [2, 1, 5, 6, 7, 4, 4]
    string = 'flask'
    return render_template('filters.html', num=num, li=li, string=string)

在templates文件夹中新建filters.html文件,在该文件中对定义的模板变量使用过滤器修改或过滤变量值。

<!DOCTYPE html>
<html>
  <head>
    <title>Jinja2 Filter Example</title>
    <body>
        {#返回变量num的绝对值#}
        <h4>绝对值:{{ num|abs }}</h4>
        {#将变量num转换为整型#}
        <h4>转换为整型:{{ num|int }}</h4>
        {#返回变量li中随机的一个元素#}
        <h4>获取随机元素:{{ li|random }}</h4>
        {#返回变量li的长度#}
        <h4>获取列表长度:{{ li|length }}</h4>
    </body>
  </head>

</html>

结果:

(4)选择结构

Jinja2支持选择结构。Jinja2提供了if、elif、else、endif,其中if、elif、else与Python关键字if、elif、else的含义相同,endif用于标识选择结构的末尾。

#注意的是,选择结构必须以{% endif %}结尾。
{% if 条件语句1 %}
    语句1
{% elif 条件语句2 %}
    语句2
……
{% else %}
语句n
{% endif %}

示例:

#app.py增加URL规则
@app.route('/query-score/<int:score>')
def query_score(score):
    return render_template('select_struct.html',score=score)

#templates文件夹新建模板文件select_struct.html
<!DOCTYPE html>
<html>
  <head>
    <title>score</title>
    <body>
        {% if score >= 85%}
            优秀
        {% elif 75 <= score < 85%}
            良好
        {% elif 60 <= socre < 75%}
            中等
        {% else %}
            差
        {% endif %}
    </body>
  </head>

</html>

结果:

(5)循环结构

Jinja2还支持循环结构,其作用是循环遍历变量中的每个元素,以便在模板文件中使用这些元素。Jinja2中循环结构与Python中的for语句用法相似。

#for、endfor均使用{% %}进行包裹,其中for标识循环结构的起始位置,endfor标识循环结构的结束位置
#且两者都不能省略。
{% for 临时变量 in 变量 %}
    语句
{% endfor %}

示例:

#app.py增加URL规则触发视图函数goods()
@app.route('/goods')
def goods():
    goods_name = ['洗碗机','电饭锅','电烤箱','电磁灶','微波炉']
    return render_template('loop_struct.html', goods_name=goods_name)

#在templates文件夹中新建模板文件loop_struct.html
<!DOCTYPE html>
<html>
  <head>
    <title>goods_list</title>
    <body>
        {% for good in goods_name %}
            <h4>{{ good }}</h4>
        {% endfor %}
    </body>
  </head>
</html>

结果:

10.消息闪现

Flask提供了向用户反馈信息的方式——消息闪现。Flask中通过在视图函数中使用flash()函数实现消息闪现的效果,不过flash()函数执行后不会立即在浏览器页面中弹出一条消息,而是需要在模板中通过get_flashed_messages()函数获取消息,并将其显示到页面中。

(1)flash()函数

flash()函数通过flask.flash导入使用,用于发送消息

flash(message, category='message')

•message:必选参数,发送闪现的消息。

•category:可选参数,消息的类别。该参数支持4种取值,分别是message、error、info和warning,其中message是默认值,表示任何类型的消息;error表示错误的消息;info表示信息消息;warning表示警告消息。

(2)get_flashed_messages()函数

 get_flashed_messages()函数是一个全局函数,可在模板的任意位置调用。

get_flashed_messages(with_categories=False , category_filter=())

•with_categories:可选参数,表示是否同时返回消息与消息类别,若设置为True,则会以元组形式返回消息和消息类别;若设置为False,则只会返回消息。

•category_filter:可选参数,表示只返回与消息类别一致的消息。

flash()函数会将发送的消息存储到session中,因此我们需要在程序中设置secret_key。 

示例:

(1)在app.py文件中定义视图函数home_page(),该函数用于判断用户的登录状态。

from flask import Flask, render_template
from flask import flash, redirect, session, request, url_for
app.secret_key = 'Your_secret_key&^52@!' # 设置secret_key
@app.route('/home')
def home_page():
    username = session.get('username')	
    # 判断session是否存储username的数据
    if 'username' in session:
        return render_template('home_page.html', username=username)
    return redirect(url_for('login'))      # 重定向到login页面

(2)在app.py文件中定义视图函数login(),获取用户在login页面输入的用户名和密码,如果用户输入错误,则通过消息闪现机制反馈给用户,反之将用户名和密码保存到session中,并将页面重定到home页面。

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        if request.form['username'] != 'admin' or \
                request.form['password'] != '123':
            flash('用户名或密码错误', category='error')
        else:
            session['username'] = request.form['username']
            session['password'] = request.form['password']
            flash('恭喜您,登录成功', category='info')
            return redirect(url_for('home_page'))
    return render_template('login.html')

(3)在templates文件夹中新建模板文件home_page.html,该模板文件用于展示home页面以及用户登录成功的消息。

<body>
    <h2>主页</h2>
    {% for message in get_flashed_messages(category_filter = ('info')) %}
        <span>{{ message }}</span>
    {% endfor %}
    <p>欢迎用户:{{ username }}</p>
</body>

(4)在templates文件夹中新建模板文件login.html,该模板文件用于展示login页面以及登录失败的消息。

<body>
<h2>用户登录</h2>
    {% for message in get_flashed_messages(category_filter = ('error')) %}
        <p class="error" style="color: red;">{{ message }}</p>
    {% endfor %}
    <form action="" method="post" class="form">
        <span>用户名:</span><br>
        <input type="text" name="username"><br>
        <span>密码:</span><br>
        <input type="password" name="password"><br>
        <p><input type="submit" value="登录"></p>
    </form>
</body>

结果:

输入/home,跳转到登录页面

用户名或密码错误

登录成功

11.静态文件的加载

(1)在模块中引用图片文件

在Flask程序中,默认情况下静态文件都存储在与项目文件同级目录的static文件夹中,该文件夹需要由开发人员创建。

- 为了能够在模板文件中引用静态文件,需要使用url_for()函数解析静态文件的URL静态文件的URL规则默认为/static/<path:filename>。

- url_for()函数需要接收两个参数,第1个参数表示端点名称,默认值为static;第2个参数filename表示静态文件的名称。

url_for('static', filename='test.png')

#以上代码解析的URL规则为/static/test.png

在模板中若要引用图片文件,可以在定义<img>标签时通过src属性规定显示图像的URL,该URL是调用url_for()函数解析静态文件的URL。

<img src="{{ url_for('static', filename='test.png') }}">

示例:

 (1)在项目的根目录下新建一个static文件夹,在static文件夹中导入图片文件flask.png;在templates目录下新建一个模板文件base.html,之后在模板文件base.html中引用图片文件flask.png。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
</head>
<body>
    <p>Flask-Logo图片</p>
    {#引用flask.png#}
    <img src="{{ url_for('static',filename='flask.png') }}">
</body>
</html>

(2)在app.py文件中定义视图函数load_staticfile()以及触发该函数的URL规则/static-file,在该函数中渲染模板文件base.html。

@app.route('/static-file')
def load_staticfile():
    return render_template('base.html')

结果:

(2)在模块中引用css文件

在模板中若要引用CSS文件,可以在定义<link>标签时通过src属性规定当前模板与CSS文件之间的关系,src属性的值为stylesheet,表示样式表;通过href属性规定被链接文档的URL,该URL是调用url_for()函数解析静态文件的URL。

<link rel="stylesheet" href="{{ url_for('static',filename='test.css') }}">

示例:

(1)新建一个CSS文件Italics.css

p{font-style:italic} 

(2) 在项目的static目录中导入CSS文件Italics.css,之后在模板文件base.html中引用CSS文件Italics.css。(其他部分与上例相同)

<head>
    <meta charset="UTF-8">
    <link rel="stylesheet" href="{{ url_for('static',filename='Italics.css') }}">
</head>

总体示例(较简单)

链接:https://pan.baidu.com/s/1U8yEFG6bX-NXFFjPa__Rzg 
提取码:yb9v


之后深入学习会继续更新!

  • 21
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值