FlaskDay04

重定向与 url_for

目录

前言

故事回到 上一篇笔记 ,我们实现了首页、注册页面的基本功能,但是实际开发往往是需要将两者联系出来,我们当然可以在注册成功之后给客户端响应一个页面,显示注册成功并显示返回首页的链接,那么用户注册成功之后就可以点击链接重新返回首页,但是这好像是远古时代才会做的事情,因为根本不符合人们使用习惯,有没有办法能够实现:注册成功之后就 “自动” 返回首页?,所谓 “自动” ,其实就是重定向。

重定向

在讲述 Python Flask Web 框架中如何重定向网址之前,先来回顾一下关于重定向的一些基本常识。

重定向分为永久性重定向和暂时性重定向,在页面上体现的操作就是浏览器会从一个页面自动跳转到另外一个页面。比如说用户访问了一个需要权限的页面,但是该用户当前并没有登录,因此我们应该给他重定向到登录页面。

  • 永久性重定向 http 的状态码是 301 ,多用于旧网址被废弃了要转到一个新的网址确保用户的访问,最经典的就是京东网站,你输入www.jingdong.com 的时候,会被重定向到 www.jd.com,因为 jingdong.com 这个网址已经被废弃了,被改成 jd.com ,所以这种情况下应该用永久重定向。

  • 暂时性重定向 http的状态码是 302 ,表示页面的暂时性跳转。比如访问一个需要权限的网址,如果当前用户没有登录,应该重定向到登录页面,这种情况下,应该用暂时性重定向。

在 flask 中,只要实例化 Flask 类,就能使用它的方法,而其中重定向是通过 flask.redirect(location,code=302) 这个函数来实现的,location 表示需要重定向到的 URL ,搭配 url_for() 函数来使用,code 表示采用哪种重定向,默认是 302 也即暂时性重定向,可以修改成 301 来实现永久性重定向。调用时,它返回一个响应对象,并将用户重定向到具有指定状态代码的另一个目标位置。其实实现机制很简单,就是向客户端(浏览器)发送一个重定向的 HTTP 报文,浏览器会去访问报文中指定的 URL 。

该函数的原型如下:

我们在这里写一个简单的例子,先初步熟悉 redirect() 函数。

# app.py
from flask import Flask, render_template, request, redirect
import settings
app = Flask(__name__)
app.config.from_object(settings)
# 路由
@app.route('/')
def index():
return render_template('index.html')
@app.route('/register', methods=['GET', 'POST'])
def register():
if request.method == 'POST':
user = request.form.get('username')
passwd = request.form.get('password')
return redirect('/')
# return '注册成功'
return render_template('register_test.html')
if __name__ == '__main__':
app.run()
# settings.py
ENV = 'development'
DEBUG = True
{#register_test.html#}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>用户注册页面</title>
</head>
<body>
<h1>用户注册</h1>
<form action="/register" method="post">
<p><input type="text" name="username" placeholder="用户名"></p>
<p><input type="text" name="password" placeholder="密码"></p>
<p><input type="submit" value="注册"></p>
</form>
</body>
</html>
{#index.html#}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>首页</title>
</head>
<body>
<a href="/register">注册</a><br>
</body>
</html>

对于上面所写的例子,有几点要说明的:

  • 所写例子简单的实现了用户主页与注册页面的基本联系,即本地调试默认打开 127.0.0.1:5000 即为首页,点击超链接可进入注册页面,在注册页面填写用户名和密码之后即可重定向到主页,另外这里只是想简单的实现 redirect() 函数的功能,所以没有对注册功能进行细节完善,在此可忽略。
  • 在本地调试的时候我们其实可以打开 chrome 开发者模式,对 network 进行观察,无论是表单 POST 请求之后的 form data,还是成功注册之后的重定向响应都能清楚看出。
  • 另外,在实际开发中,开发者模式下的 headers 中如果没有Form Data(post 方法),可以看看表单中的 input 标签是否忘记写 name 属性,这是很多 WEB 开发新手经常犯的错误。

调试结果如下,成功注册之后成功重定向回主页,而这里我们只是简单使用了单纯的路径即 redirect('/'),但往往实际开发中,我们不会去记住路由,因为实际开发中,我们可能会创建几十个甚至上百个路由,所以往往实际开发中会搭配 url_for() 使用,这里可以简单的类比为我们往往更想去记住一个网站的域名,而不是实际的 IP 地址。

url_for()

url_for 的作用是为每一个视图函数添加一个名字,在实际开发中,路径有可能会很长,这时就可以通过另一个视图函数名字来指向该路径。源码如下:

这就是我们刚才铺垫了这么久的原因,对于上面的代码存在的问题就是,假如我不是想重定向回首页(因为首页 URL 为 '/' 比较容易记住),而是一个 “又长又臭” URL 呢,而我却不想记住这个 “ 又长又臭的URL”,但是如果我记得这个地址 “又长又臭”,我们可以给这个路由命名为又长又臭,方便实际开发的日后使用。所以 url_for() 跟的参数就是 '又长又臭' ,如果有留心注意,url_for(endpoint) 中的 endpoint,其实是 route() 函数中的参数:

那么就把重定向与 url_for() 结合进行使用,实现方法很简单:为首页视图函数添加 endpoint 参数的值,该值其实就代表了我给这个视图函数起了一个别名,这样就可以通过使用 url_for() 方法实现重定向。

from flask import Flask, render_template, request, redirect, url_for
import settings
app = Flask(__name__)
app.config.from_object(settings)
# 路由
@app.route('/',endpoint='shouye')
def index():
return render_template('index.html')
@app.route('/register', methods=['GET', 'POST'])
def register():
if request.method == 'POST':
user = request.form.get('username')
passwd = request.form.get('password')
# return redirect('/')
# return '注册成功'
return redirect(url_for('shouye'))
return render_template('register_test.html')
if __name__ == '__main__':
app.run()

这就是 URL 反转,即知道视图函数的名称,就可以知道 URL。而 URL 正转就是知道 URL 找视图函数。