python web之flask学习(二)

上一节完成第一个入门程序hello world后,这一节学习flask中url的知识。

 

一、动态URL规则

URL中是可以添加变量部分的,即将同一种规则的url抽象成一种模式,比如/aaa/1、/aaa/2、/aaa/3...如果不抽象路径,就需要写上n次:

@app.route('/aaa/1')
@app.route('/aaa/2')
@app.route('/aaa/3')
...
def aaa():
    return 'aaa执行'

所以,如果有一种方式可以把数字部分全部抽象成一个变量,不就方便多了吗?写法如下:

@app.route('/aaa/')
def aaa(id):
    return 'aaa-id:{}'.format(id)

也就是说将路径中的某一部分作为变量传入视图函数中,在这里将对应的路径作为参数传递给aaa函数。

细心的朋友可以看到,这样接收的变量是没有指定类型的,其实这里默认为字符串类型,指定类型以及自带的类型如下:

  • string:接受任何无斜杠"/"的文本,这是默认的类型
  • ing:接受整数
  • float:接受浮点数
  • path:与string类似但是接受斜杠
  • uuid:只接受uuid字符串,多用于图片的访问
  • any:可以指定多种路径,但需要传参

       @app.route('/aaa//')

       那么访问/aaa/a/和/aaa/b/都会符合这个路径,/aaa/a/的variable_name就是a

 

二、自定义URL转换器

如果自带的转换器(就是上面说的类型指定)不能满足需求,还可以自定义转换器,

假如现有需求为:通过访问localhost:5000/demo1/flask+django就能同时看django和flask的帖子,那么自带的转换器就无法解决。

自定义URL转换器,实现对上述url的转换。

from flask import Flask
from werkzeug.routing import BaseConverter
from urllib import parse as urlparse

app = Flask(__name__)

class MyConverter(BaseConverter):
    def __init__(self, url_map, sep='+'):
        super(MyConverter, self).__init__(url_map)
        self.sep = urlparse.unquote(sep)

    def to_python(self, value):
        return value.split(self.sep)

    def to_url(self, values):
        return self.sep.join(BaseConverter.to_url(value=value) for value in values)


app.url_map.converters['list'] = MyConverter


@app.route('/demo1//')
def demo1(page_names):
    return "page_names={" + ','.join(page_names) + '}'

if __name__ == '__main__':
    app.run(debug=True)

然后运行并访问:

需要注意自定义转换器继承者BaseConverter,要设置to_python和to_url两个方法。

  • to_python:将路径转换为python对象
  • to_url:将python对象转换为url形式

三、HTTP方法

http有多种访问方法,默认的情况下,app.route装饰器只响应GET请求,向app.route装饰器中传递methods参数可以修改响应的类型。

@app.route('/aaa',methods=['GET','POST'])
@app.route('/bbb/',methods=['DELETE','POST'])

以下为http方法和常用场景:

GET:获取资源

HEAD:获取资源但是只关心消息头,不返回实际内容。

POST:创建新的资源,是表单最常用的请求类型

PUT:替换资源或者创建资源

DELETE:删除资源

OPTIONS:获取资源支持的所有HTTP方法

PATCH:局部更新,修改某个资源

在国内很多只用了GET和POST两种方法,偏离REST的风格。

四、构造URL、跳转和重定向

用url_for构建URL,它接受函数名作为第一个参数,也接受对于URL规则的变量部分的命名参数,未知变量部分会添加到URL末尾作为查询参数,使用url_for构建URL的原因:

  • 在以后有更改时,只需一次修改URL,而不用到处替换
  • 构建URL会转义特殊字符和Unicode数据

以下代码:

...引入相关函数等...

app = Flask(__name__)

@app.route('/demo3_1/')
def demo3(id):
    return "demo3:{" + id + '}'


@app.route('/demo3_2/')
def demo3_2(a):
    return url_for('demo3', a=a, id=100, s='多余参数')

if __name__ == '__main__':
    app.run(debug=True)

当访问/demo3_2/2/时:

即,url_for返回第一个参数(函数名)对应的url,这里就是/demo3_1/

显然接受变量id为路径,而变量a和s则作为查询参数和/demo3_1/id拼接,

最终得到上图结果。

url_for只是将第一个参数对应url和参入的参数进行拼接,并不会执行第一个参数对应的函数。

跳转和重定向

跳转(状态码301):将对旧网址的访问转向新网址,有页面永久性转移的概念。

重定向(状态码302): 表示页面是暂时性的转移。

@app.route('/demo4')
def demo4():
    name = request.args.get('name')
    if not name:
        return redirect(url_for('demo4_2'))
    user_agent = request.headers.get('User-Agent')

    return 'name:{0},User-Agent:{1}'.format(name, user_agent)


@app.route('/demo4_2',methods=['GET','POST'])
def demo4_2():
    if request.method == 'POST':
        user_id = request.form.get('user_id')
        return 'User-ID:{}'.format(user_id)
    else:
        return 'login page'


@app.route('/demo4_3')
def demo4_3():
    abort(401)
    return 'never executed'

1. 访问demo4的请求会被301跳转到/demo4/上。

2. request.headers 存放请求头的信息

3. request.method 为请求类型

4. abort(401)将放弃请求,禁止访问,其后的代码永远不会执行

5. redirect为重定向,根据传入的url进行重定向,通常配合url_for

五、404请求处理

web开发中少不了处理404请求的情况,在flask中以下两种方式都能对404请求进行处理,其中第二种方式更加灵活,可以去设置cookie,头信息等。

@app.errorhandler(404)
def not_found(error):
    return render_template('error.html'),404

@app.errorhandler(404)
def not_found(error):
    rsp = make_response(render_template('error.html'),404)
    return rsp

 

 

 

你可能感兴趣的:(flask,flask,python,web)