-学习笔记-
通过 URL 传递参数,接收参数,利用试图函数实现参数到 URL 转换,自定义 URL 转换
URL 是 Uniform Resource Locator 的简写,统一资源定位符。
一个 URL 由以下几部分组成:
scheme://host:port/path/?query-string=xxx#anchor
|
- scheme:代表的是访问的协议,一般为 http 或者 https 以及 ftp 等。
- host:主机名,域名,比如www.baidu.com。
- port:端口号。当你访问一个网站的时候,浏览器默认使用 80 端口。
- path:查找路径。比如:www.jianshu.com/trending/now,后面的trending/now就是path。
- query-string:查询字符串,比如:www.baidu.com/s?wd=python,后面的wd=python就是查询字符串。
- anchor:锚点,后台一般不用管,前端用来做页面定位的。
传递参数
传递参数的语法是:/<参数名>/
。然后在视图函数中,也要定义同名的参数。
@app.route('/') @app.route('/list/') @app.route('/p/<float:article_id>') @app.route('/u/<uuid:user_id>/') @app.route('/<any(blog,article):url_path>/<id>/')
|
参数的数据类型
- 如果没有指定具体的数据类型,那么默认就是使用
string
数据类型。
int
数据类型只能传递int
类型。
float
数据类型只能传递float
类型。
path
数据类型和string
有点类似,都是可以接收任意的字符串,但是path
可以接收路径,也就是说可以包含斜杠。
uuid
数据类型只能接收符合uuid
的字符串。uuid
是一个全宇宙都唯一的字符串,一般可以用来作为表的主键。
any
数据类型可以在一个url
中指定多个路径。
@app.route('/<any(blog,article):url_path>/<id>/') def detail(url_path,id): if url_path == 'blog': return '博客详情:%s' % id else: return '博客详情:%s' % id
|
接收用户传递的参数
- 第一种:使用
path
的形式(将参数嵌入到路径中),就是上面讲的。
- 第二种:使用查询字符串的方式,就是通过
?key=value
的形式传递的。
@app.route('/d/') def d(): wd = request.args.get('wd') return '参数是:%s' % wd
|
URL 转换器
url_for
将视图函数名字后面的参数传递给url
。
如果传递的参数之前在url
中已经定义了,那么这个参数就会被当成path
的形式给url
。如果这个参数之前没有在url
中定义,那么将变成查询字符串的形式放到url
中。
from flask import Flask,url_for,request ...
@app.route('/list/<page>/') def my_list(page): return 'my list'
print(url_for('my_list',page=1,count=2))
|
- 将来如果修改了
URL
,但没有修改该 URL 对应的函数名,就不用到处去替换 URL 了
@app.route('/post/list/<page>/') def my_list(page): return 'my list' url = url_for('my_list',page=1,count=2)
|
- url_for 会自动的处理那些特殊的字符,不需要手动去处理。
@app.route('/login/') def login(): return 'login'
url = url_for('login',next='/')
|
自定义 URL 转换器
URL 参数的数据类型通过routing.py
中的Unicode/Float/Any/Path/Number Converter
等类指定,使用了默认转换器
可以自定义类型 URL 转换器和运算符 URL 转换器
- 实现一个类,继承自
BaseConverter
。
- 在自定义的类中,重写
regex
,也就是这个变量的正则表达式。
- 将自定义的类,映射到
app.url_map.converters
上。
from flask import Flask,url_for from werkzeug.routing import BaseConverter
class TelephoneConveter(BaseConverter): regex = r'1[85734]\d' app.url_map.converters['tel'] = TelephoneConverter
@app.route('/telephone/<tel:my_tel>/') def my_tel(my_tel): return '您的手机号码是:%s' % my_tel
class OpratorConverter(BaseConverter): def to_python(self, value): return value.split('+')
def to_url(self, value): return "+".join(value) app.url_map.converters['oprator+'] = OpratorConverter
@app.route('/posts/<oprator+:boards>/') def posts(boards): print(boards) return "您提交的板块是:%s" % boards
|
URL 重定向
重定向在页面上体现的操作就是浏览器会从一个页面自动跳转到另外一个页面。比如用户访问了一个需要权限的页面,但是该用户当前并没有登录,因此我们应该给他重定向到登录页面。
- 永久性重定向:
http
的状态码是301
,多用于旧网址被废弃了要转到一个新的网址确保用户的访问。
- 暂时性重定向:
http
的状态码是302
,表示页面的暂时性跳转。比如访问一个需要权限的网址,如果当前用户没有登录,应该重定向到登录页面,这种情况下,应该用暂时性重定向。
flask
中有一个函数叫做redirect
,可以重定向到指定的页面。
from flask import Flask,request,redirect,url_for
app = Flask(__name__)
@app.route('/login/') def login(): return '这是登录页面'
@app.route('/profile/') def profile(): if request.args.get('name'): return '个人中心页面' else: return redirect(url_for('login'))
|
视图函数的响应
- 可以返回字符串:flask 会创建 werkzeug、wrappers、Response 对象,状态码 200,MIME 类型
test/html
,然后返回 Response 对象
from flask import Response ... @app.route('/list/') def list(): Response('Hello World!')
|
还可以通过 make_response 进行创建
form flask import make_response @app.route('/list/') def list(): return make_response('list page.')
|
- 可以返回元组:元组的形式是(Response,Status,header)
不一定三个都要写,写两个也是可以的,status 返回 200,header 为列表或字典。返回的元组,其实在底层也是包装成了一个Response
对象。
return 'list',200,{'NAME':'kevin'}
@app.errorheader(404) def not_found(): return 'not found',404
|
- 直接返回合法的响应对象
resp = Response('list') resp.set_cookie('country','china') return resp
|
- 以上条件不满足,则进行自定义响应
继承自Response
类。
实现方法force_type(cls,response,environ=None)
。
指定app.response_class
为你自定义的Response
对象。
如果视图函数返回的数据,不是字符串,也不是元组,也不是 Response 对象,那么就会将返回值传给force_type
,然后再将force_type
的返回值返回给前端。
class myResponse(Response): def force_type(cls, response, environ=None): return Response('return error.')
app.response_class = myResponse
|
from flask import jsonify ... class myResponse(Response): def force_type(cls, response, environ=None): if isinstance(response,dict): response = jsonify(response) return super(myResponse, cls).force_type(response, environ)
app.response_class = myResponse
|