Flask 请求和响应

本文介绍了Flask中请求调度的原理,包括HEAD、OPTIONS、GET等请求方法以及如何使用@app.route装饰器处理请求。此外,详细阐述了Flask中的上下文、响应处理,如元组响应、Response对象、redirect、abort函数以及模板渲染,特别是Jinja2模板引擎的使用,包括变量、过滤器和控制语句等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、请求调度

浏览器通过URL访问Flask服务器时,要通过URL和视图函数的映射关系表找到处理该URL的视图函数(该视图函数返回响应给浏览器),这个映射关系可以通过app.route修饰器建立。下面给出了上一篇文章中的helloworld例子

#coding:utf-8

from flask import Flask

app=Flask(__name__)

@app.route("/")
def index():
	return "<h1>Hello World!</h1>"

@app.route("/user/<name>")
def user(name):
	return "<h1>Hello,%s</h1>"%name

if __name__=="__main__":
	app.run(debug=True,host="0.0.0.0",port=8000)
例子中将程序根目录URL和视图函数index映射起来。可以在python命令行通过app.url_map查看这种映射关系:

HEAD,OPTIONS,GET是URL与视图函数的请求方法,HEAD和OPTIONS为Flask自动处理,功能分别为获取响应报文首部(即不发送报文主体)和询问访问某URL支持的方法。 可以通过route修饰器的methods参数为路由指定不同的请求方法,比较常用的是GET和POST方法。

二、程序和请求上下文

视图函数在处理请求时,有时需要获取一些其他对象信息,这个时候的处理方式是使用线程独立的全局变量而非传参,比如请求对象request等(其他上下文全局变量如下表)。上下文可以理解为对这些对象的引用池,方便我们随时访问这些变量。

Flask上下文全局变量
变量名上下文说明
current_app程序上下文当前激活的程序实例,比如helloworld例子中的app
g程序上下文用作处理请求时的临时存储,每次请求都重设
request请求上下文请求对象,包含了客户端HTTP请求的内容,例如获取客户端请求报文头部中包含的
User-Agent信息:request.headers.get("User-Agent")
session请求上下文用户会话,字典格式,存储请求间需要记住的信息

从flask中引入上下文变量就可以使用这些变量,例如下面的视图函数返回请求中的User-Agent给客户端:

@app.route("/user-agent/")
def get_user_agent():
	user_agent=request.headers.get("User-Agent")
	return "<p>%s</p>"%user_agent

输入URL http://127.0.0.1:8000/user-agent/ 访问:


Falsk上下文在请求之前会先激活,请求处理完毕则会将其删除。

三、响应

响应即视图函数的返回值,上述例子中的返回都很简单,直接将html代码作为返回值。但是Flask Http协议的返回值中通常还会有以下几种不同的格式:

1.元组:(html字符串,状态码,返回报文首部信息)

状态响应码:Flask默认为200(故此时可省略),即请求成功处理。一些常用的状态码如下:

    2xx成功:200(请求成功处理)、204(请求成功处理但无资源返回)、206(请求部分内容成功,在请求报文实体首部中包含需要的资源)

    3xx重定向:301(永久性重定向,表示访问资源已经更新了URI,通常在返回报文首部信息增加Location提示新的URI,如果访问的URI保存为书签,则会被更新为新的URI)

                          302(临时性重定向,表示此次访问资源被重定向到新的URI,并非永久,不更新书签)

                          304(资源不满足客户端请求条件,比如请求的是某时间点后有更新则返回新资源,但资源在该时间点后无更新,被规在3xx,但和重定向没啥关系)

    4xx客户端错误:400(客户端请求存在错误,应该修改请求后再次发送)、401(未授权)、403(禁止访问)、404(找不到访问的资源)

    5xx服务器错误:500(服务器处理请求时出现错误)、503(服务器忙碌或者停机维护无法处理请求)

返回报文首部信息:比如包含重定向时,包含URI的Location信息,{"Location":"http:xxx"},很少用到,可省略。

2.Response对象

make_response()函数生成Response对象,函数接受1、2、3个参数,参数意义和元组形式一致,可以对响应进行一些设置后返回,比如设置cookie。

from flask import make_response
@app.route("/response/")
def response():
	response=make_response("<h1>This response carries a cookie</h1>")
	response.set_cookie("answer","42")
	return response

浏览器访问后再次请求f12查看请求头中包含设置的cookie。


3.使用redirect函数

常用来跳转到重定向的url,比如return redirect("http://www.baidu.com/")

from flask import redirect
@app.route("/redirect")
def test_redirect():
	return redirect("http://www.baidu.com/")

4.使用abort函数处理错误

通常用来抛出异常,把控制权交给web服务器返回异常,比如:abort(404)

5.使用渲染模板

前述的例子都太简单,通常一个http请求的处理可能会涉及复杂的业务逻辑和表现逻辑,比如在某网站注册账号的时候,通过POST方法提交一个表单给服务器,服务器需要通过表单内容来生成一个新用户并进行数据库相关操作,然后再给客户端返回一个处理完毕的响应。模板的作用是处理表现逻辑,把业务逻辑和表现逻辑分开,提升代码的可维护性。Flask使用了Jinja2模板引擎。

最简单的helloworld模板可以这样使用:在helloworld.py同一目录下创建templates文件夹,然后把模板文件放在文件夹中,比如'helloworld.html",然后通过Flask的render_template函数渲染模板,并作为视图函数返回值即可。

from flask import render_template
@app.route("/")
def index():
	return render_template("helloworld.html")
模板文件包含响应文本:

访问“http://127.0.0.1:8000”可以看到效果和原来一样~

复杂的响应文本中会包含逻辑语句以及变量,变量真实值可以通过render_template传递。使用真实值替换模板中的变量,得到最终的响应文本,这个过程即称为渲染模板。

三、模板

1.变量

模板中的变量使用双大括号占位+变量名表示:比如{{ name }}。我们可以把helloword例子的user视图函数替换成模板渲染后返回:

新增模板文件templates/user.html:

<h1>Hello,{{ name }}</h1>
user视图函数:

@app.route("/user/<name>")
def user(name):
	return render_template("user.html",name=name)
访问url可以看到效果:


上述例子使用url中的<name>字符串作为变量传递给视图函数,视图函数又将之传递给模板渲染后返回响应。Jinja2可以识别复杂的对象,比如可以把一个用户对象传递给模板,然后在模板中访问对象的各个属性变量。例如 {{ user.username }} 获取user对象的username属性。

变量可以用过滤器修改,Jinja2提供了一些常用的过滤器,使用格式为{{ 变量名|过滤器名 }}比如要将上述模板中的name变量全部以大写字母显示,可以修改user.html如下:

效果:

常用的Jinja2过滤器有:

过滤器名说明
safe渲染值时不转义,默认情况下安全起见,jinja2会将html标签在渲染时会被转义掉(比如左尖括号转义为&lt;),使用这个过滤器可以保护这些标签不被过滤(对可信的变量比如服务器自己生成的html串采用)
capitalize首字母大写,其他字母小写
lower小写形式
upper大写形式
title每个单词首字母大写
trim去掉值首尾空格
striptags把值中所有的HTML标签删除

2.控制语句,结构: {% 语句 %}

①条件语句

{% if name %}
    Hello,{{ user }}!
{% else %}
    Hello,Stranger!
{% endif %}

②for循环

<ul>
    {% for user in users %}
        <li>user.username</li>
    {% endfor %}
</ul>

③宏 定义格式类似于函数,比如可以定义一个宏,然后再调用这个宏,使用宏定义的格式替换调用的部分

定义:关键字macro

{% macro render_comment(comment) %}
	<li>{{ comment }}</li>
{% endmacro %}
调用:{{ 宏名(参数) }}

<ul>
	{% for comment in comments %}
		{{ render_comment(comment) }}
	{% endfor %}
</ul>
也可以将宏单独保存在一个文件中,再调用的文件中使用 import语句引入。

{% import "_macro.html" as macro %}
<ul>
	{% for comment in comments %}
		{{ macro.render_comment(comment) }}
	{% endfor %}
</ul>
④导入代码片,其作用是代码重用,如下可将_comments.html中的代码片段包含到模板文件中。

{% include "_comments.html" %}
⑤模板继承,比如同一个网站的不同网页通常有一些相同或相似的格式,这时候可以把这些相似的样式写在一个基模板中,同时预留可供扩展的block区域,其他页面可通过继承该模板,并在对应block区域扩展自己页面的内容:

基模板base.html:

<!DOCTYPE html>
<html>
<head>
	{% block head %}
	<title>{% block title %}{% endblock %}-My App</title>
	{% endblock %}
</head>
<body>
	{% block body %}
	{% endblock %}
</body>
</html>
继承自base.html的index.html:

{% extends "base.html" %}
{% block title %}Index{% endblock %}
{% block head %}
    {{ supper() }}
    <style>
    </style>
{% endblock %}
{% block body %}
<h1>Hello World</h1>
{% endblock %}

子页面扩展的部分会替换基模板相同的block区域包含的部分,如果有内容需要继承基模板同时扩展新内容,使用supper()来获取基模板内容。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值