文 / 秦未
今天我学习了Flask路由相关的知识,对route也有了一定的了解,一般对静态网站来说一个路由对应一个网址,不会有太多变化,但对于动态网站,我们需要动态路由,这意味着路由是可变的,但它仍然具有规则。
为了了解Flask默认的路由规则,我们先来看个简单的示例:
先增加一个路由和函数:
# /app/app.py
@app.route('/user/<username>')
def user(username):
return F'<h1>{username}</h1>'
这里我们做了什么?
我们指定了一个url,其中有一个参数叫username,<>包裹的内容代表为这个变量取名,接着user函数内要传递这个参数,然后我们将它return出去了。
当然,这是Flask最简单的一个路由定义方式,我们要注意路由中的变量名要和函数名保持一致,否则就会报错。
<>里面只有一个变量名代表它接收任何类型的参数,当我们需要指定接收参数类型时,只需要在变量名前加
类型: 即可,
Flask默认支持的转换器有:{'default': , 'string': , 'any': , 'path': , 'int': , 'float': , 'uuid': }
Flask版本不同支持的转换器数量也会有所不同,最新的支持多一些。
我们再做个简单示例,将上面那个路由和函数再修改成这样:
# /app/app.py
@app.route('/user/<int:user_id>')
def user(user_id):
return F'<h1>{user_id}</h1>'
运行,进入网站为http://127.0.0.1:5000/user/2,会发现页面显示2,改一下url后面的数字,内容也随着改变。
我们发现其实Flask默认支持的转换器已经可以应对大多数情况了,不过如果能支持正则,我想应该更好了,如何让Flask支持正则呢?其实很简单,我们修改一下代码:
注意:前面带 + 号的为新增加内容,复制时请自行删除 + 。
# /app/app.py
from flask import Flask, render_template
+ from werkzeug.routing import BaseConverter
+ class RegexConverter(BaseConverter):
def __init__(self, url_map, *items):
super(RegexConverter, self).__init__(url_map)
self.regex = items[0]
app = Flask(__name__)
+ app.url_map.converters['regex'] = RegexConverter
@app.route('/')
def index():
return render_template('blog/index.html', **{
'text': 'Hello, World',
})
@app.route('/about')
def about():
return '<h1>about</h1>'
@app.route('/user/<username>')
def user(username):
return F'<h1>{username}</h1>'
if __name__ == '__main__':
app.run(debug=True)
这样我们就可以在路由中使用正则了,具体的用法是这样的:
路由中填:<regex("规则"):名称>
我想学过正则的同学都应该知道如何填写。
好了,我们再来研究一下路由,你会发现:
@app.route('/about')
@app.route('/about2/')
这两种路由是有所区别的,区别不在于后面那个数字2,而在于 “ / ”,在浏览器的世界里,URL如果后面带斜杠代表这是一个文件夹,默认访问该文件夹的index.html文件,所以@app.route('/about2/')其实是@app.route('/about2/index.html'),只不过由于我们指定了路由,所以后面的被隐藏掉了,而@app.route('/about')就代表@app.route('/about.html'),其中你又会发现访问 http:/127.0.0.1:5000/about2时,浏览器会默认给你加上 “ / ” , 这样能避免歧义,给用户更友好的浏览体验,因为用户可能会忘记加 “ / ”,所以具体怎么用全看自己想法了。
接着我们又遇到一个问题,如果要用多个URL指向同一个函数怎么办?
其实很简单,只需要在路由之前再加一个路由即可,类似这样 :)
@app.route('/about')
@app.route('/about2/')
def ...
然后我又接触到HTTP请求的方式,我们都知道HTTP请求的方式有很多种,我查了一下一共有8种,当然对我们新手来说,不用了解那么多,一般遇到的也就GET和POST,默认是GET的访问方式,路由可以区别两种方法,只要我们定义了,那么路由只会响应该方法的请求,而定义这两种情况的URL一般是用在登录和注册页面,所以我们先新增加一个路由和函数,模拟一个登录页:
@app.route('/login/', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
return F'<h1>{request.method}</h1>'
return render_template('blog/login.html', method='GET')
先解释这个路由和函数, methods=['GET', 'POST'] 里面定义了只接收两种请求方式GET和POST,request是Flask函数自带的一个方法,我们需要导入,然后它也有一个方法是获取当前请求的请求方式,即:request.method,所以我做了一个判断,如果该方式为POST,就输出该变量,否则就正常输出login页面。
事先我也做好一个login.html页面:
<!--/app/templates/blog/login.html-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登录页</title>
</head>
<body>
<form action="{{ url_for('.login') }}" method="post">
<input type="text">
<input type="submit">
</form>
</body>
</html>
并且首页增加一个链接:
<!--/app/templates/blog/index.html-->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>首页</title>
<link rel="stylesheet" href="{{ url_for('static', filename='blog/style.css') }}">
</head>
<body>
<h1>{{ text }}</h1>
<a href="{{ url_for('.about') }}">about</a>
<a href="{{ url_for('.login') }}">login</a>
</body>
</html>
运行访问。
实际情况:从首页点击进入,请求方式为默认的GET,所以进入正常的login页面,点击提交,方式为POST,输出该变量。
好了,今天就学这么多,明天是Flask的请求上下文与响应。
---end---