FLASK学习杂记(二)FLASK路由
一、URL函数映射
1.route()装饰器
在FLASK中,url要与函数映射,需要使用route()装饰器将二者绑定。
调用app.route()装饰器并指定url(’/’):
@app.route('/')
def hello_world():
return 'Hello World!'
在浏览器中输入127.0.0.1:5000/(127.0.0.1为默认ip,5000为默认端口)
指定url /index
@app.route('/index')
def index():
return '这里是index'
2.url尾端/重定向行为
# test1
@app.route('/test1')
def test1():
return '这里是test1'
# test2
@app.route('/test2/')
def test2():
return '这里是test2'
对于test1,url尾部没有/,在访问时尾部添加斜杠即’/test1/’,会报404错误,前端显示Not Found。
而对于test2,若未在其尾部添加斜杠即’/test2’,Flask会自动进行重定向,在尾部自动添加/,即’/test2/’。
test1与test2的区别类似与文件与文件夹,test1可以保持url唯一,建议在定义路由时候在末尾加上’/'即test2的写法,可以避免访问错误。
3.变量规则
使用<>可以在url添加变量,作为关键字参数传给对应函数,默认的变量为string类型即字符串,若要使用其他类型,则需要用<类型:变量名>的方式来定义。
@app.route('/variate1/<v1>/')
def variate1(v1):
print('v1的类型为',type(v1))
print('v1为',v1)
return '这是v :%s'%(v1)
传入一个int类型的参数
@app.route('/variate2/<int:v2>/')
def variate2(v2):
print('v2的类型为',type(v2))
print('v2为',v2)
return '这是v :%s'%(v2)
传入一个path类型的参数
@app.route('/variate3/<path:v3>/')
def variate3(v3):
print('v3的类型为',type(v3))
print('v3为',v3)
return '这是v :%s'%(v3)
变量类型
类型 | 注释 |
---|---|
string | 默认值,不接受有/的文本 |
int | 整数类型 |
float | 正浮点类型 |
path | 类似于string,可以有/ |
uuid | 接受uuid字符串 |
4.HTTP协议与查询字符串传参
flask默认路由只回应GET请求,可以通过methods参数来设置可回应的请求类型,此时可以导入request方法来判断请求类型。
from flask import request
@app.route('/request',methods=['POST','GET'])
def requ():
return request.method
通过查询字符串形式所传的参数可以通过request方法来获取
from flask import request
@app.route('/req',methods=['POST','GET'])
def req():
if request.method == 'GET':
res = request.args.get('id')+'get'
elif request.method == 'POST':
res = request.form.get('id')+'post'
return res
5.url_for()构建url
url可以映射到函数中,知道函数名,可以通过url_for()来获对应的url(url_for官网详解),url_for()可以传入任意个关键字参数,即使函数中没有对应形参。
from flask import url_for
@app.route('/test1')
def test1():
return '这里是test1'
@app.route('/variate1/<v1>/')
def variate1(v1):
print('v1的类型为',type(v1))
print('v1为',v1)
return '这是v :%s'%(v1)
# 启动时
with app.test_request_context():
print(url_for('test1'))
print(url_for('variate1',v1=2))
print(url_for('variate1', v1=2,id=2))
print(url_for('variate1', v1=2, id=2,p='l'))
print(url_for('variate1', v1=2, id='/l'))
可以看到传入的/会被自动转义成%2F
6.add_url_rule()定义映射
add_url_rile()可以构建url,利用其中view_func参数指定要映射的函数,甚至可以通过endpoint来修改url的名字。
@app.route('/endpoint/')
def endp():
print(url_for('profile'))
print(url_for('r'))
return 'endpoint'
def profile():
return 'profile'
def rename():
return 'rename'
app.add_url_rule('/profile/',view_func=profile)
app.add_url_rule('/rename/',endpoint='r',view_func=rename)
此时在控制台打印出:
这时使用原来的名字(rename)会报错
二、页面响应
1.页面跳转重定向
在我们访问页面时经常遇到未登录时,会自动跳转到登录页面,这就存在一个重定向行为即浏览器从一个页面跳转到另一个页面。
常用重定向方式有:
- 301永久性重定向,往往用在弃用网址转移到新网址上,以确保用户能正常访问。
- 302暂时性重定向,如在访问一个需要登录权限的url时,而此时未登录,就需要重定向到登录页面,进行登录。
flask通过redirect()来实现url的重定向。这里使用url_for()来获取url,避免url更改可能产生的错误。
from flask import request
from flask import url_for
from flask import redirect
@app.route('/login/')
def login():
return '这里是登录'
@app.route('/commit/')
def commit():
name = request.args.get('name')
return name if name else redirect(url_for('login'),code=302)
可以看到输入url时为带name,会重定向到login,状态码为302。在地址栏输入http://127.0.0.1:5000/commit/?name=Tom则会正常进入commit页面,状态码为200
2.函数return类型
函数return的类型可以是string、tuple、dict、Response。
string、Response
#string
@app.route('/retstring/')
def ret_string():
return '这是一个string'
#Response
@app.route('/retresponse/')
def ret_response():
return Response('这是一个Response')
这里可以看到通过string返回和通过Response返回在前端所展示的格式一直,是由于返回的是string类型时,flask会根据这个string和缺省对象生成一个Response再返回,本质返回的还是Response。
tuple
tuple返回的格式为 (response, status) 、 (response, headers) 或者 (response, status, headers),response为响应内容,status为状态码,headers 是一个由额外头部值组成的列表 或字典
# tuple
@app.route('/rettuple/')
def ret_tuple():
return '这里是返回的tuple',201,{'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.11 TaoBrowser/2.0 Safari/536.11'}
可以看到rettuple的状态码、User-Agent均变成所设置的。
dict
@app.route('/retdict/')
def ret_dict():
return {1:'Tom',2:'Kitty'}
返回字典时,会被转成json格式返回给前端。
jsonify()
如果要返回其他类型的数据如list,通过return直接返回会报错,此时可以通过josnify()函数将list转成josn格式再返回。
# 直接返回list
@app.route('/retjson/')
def ret_json():
return [1,2,3,4,5]
# list转换成josn再返回
from flask import jsonify
@app.route('/retjson/')
def ret_json():
return jsonify([1,2,3,4,5])
三、类视图
1.标准类
flask.views.View中通过dispatch_request()方法返回,未重写的dispatch_request() 会raise NotImplementedError错误。类视图继承flask.views.View后需要对dispatch_request()进行重写。
类视图定义后要借助add_url_rule()进行url映射,这时要用as_view()来指定url名称。
class Testview(views.View):
def dispatch_request(self):
return 'class view'
def test(self):
return 'test'
app.add_url_rule('/test/',view_func=Testview.as_view('test'))
2.公共变量返回
对于两个类视图有相同变量的情况,可以将公共部分放在一个类中,让两个视图类继承。
class CommonView(views.View):
def __init__(self):
super().__init__()
self.context = {
'name':'Tom'
}
class LoginView(CommonView):
def dispatch_request(self):
return render_template('login.html',**self.context)
class RegisterView(CommonView):
def dispatch_request(self):
return render_template('register.html',**self.context)
app.add_url_rule('/login/',view_func=LoginView.as_view('login'))
app.add_url_rule('/register/',view_func=RegisterView.as_view('register'))
login
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>login</title>
</head>
<body>
<h1> welcome to login : {{ name }}</h1>
</body>
</html>
register
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>register</title>
</head>
<body>
<h1> welcome to register:{{ name }}</h1>
</body>
</html>