• 2 URL的玩法


    preface

    这里我主要说说flask的URL玩法
    include:

    1. 动态URL规则
    2. 自定义URL转换器
    3. HTTP方法
    4. 唯一的URL
    5. 构造URL
    6. 跳转和重定向

    动态URL规则

    URL规则可以添加变量部分,也就是服务器同种规则的URL抽象成一个URL模式,如/item/1/,/item/2等等。为了不需要写那么多的url,我们可以是匹配URL,如下所示:

    @app.route('/item/<id>/')
    def item(id):
        return "hi guy,it is {} ".format(id)
    

    尖括号的内容就是动态的。凡事匹配到/item/前缀的URL都会映射到这个路由上,在内部通过id作为参数而获得。
    他使用了特殊的字段标记<variable_name>,默认的类型是字符串。如果有需要指定参数类型的,需要标记成converter:variable_name这样的格式,converter有下面几种。

    1. string: 接受没有任何斜杠“/”的的文本,默认就是
    2. int: 接受整形
    3. float:接受浮点型
    4. path:和默认的相似,但也接受斜杠
    5. uuid: 只接受uuid字符串。
    6. any: 可以指定多种路径,但是需要传入参数。
    @app.route('/<any(a,b):page_name>/')
    

    访问/a/和访问/b/都符合这个规则,/a/对应的就是page_name就是a。
    如果不希望定制子路径,还可以通过传递参数的方式。比如/people/?name=a,/people/?name=b,这样通过name=request.args.get('name') 获得传入name的值。如果是POST的方法,那么表单参数通过requests.form.get('name')获得。

    自定义URL转换器

    Reddit可以通过在URL中用个加号(+)隔开各个社区的名字,方便同时查看多个社区的帖子。比如访问“http://reddit.com/r/flask+listp” ,就可以同时看flask和lisp两个社区的帖子。我们自定义一个转换器来实现这个功能,它还可以设置所使用的分隔符,不一定使用加号(+)。
    代码如下:

    # coding:utf-8
    import os
    import sys
    import urllib
    from flask import Flask
    from werkzeug.routing import BaseConverter
    
    path = os.path.dirname( os.path.dirname( __file__ ) )
    sys.path.append( path )
    app = Flask(__name__)
    
    class ListConverter(BaseConverter):
        def __init__(self,url_map,separator='+'):
            super(ListConverter,self).__init__(url_map)   # 重写父类的方法
            self.separator = urllib.unquote(separator)
    
        def to_python(self, value):
            return value.split(self.separator)
    
        def to_url(self,values):
            return self.separator.join(super(BaseConverter,self).to_url(value) for value in values)
    
    
    app.url_map.converters['list'] = ListConverter
    
    @app.route('/list1/<list:page_names>/')
    def list1(page_names):
        return "Separator: {} {} ".format('+',page_names)
    
    @app.route('/list2/<list(separator=u"|"):page_names>/')
    def list2(page_names):
        return "Separator: {} {} ".format("|",page_names)
    
    if __name__ == '__main__':
        app.run(host='0.0.0.0',port=9000)    
    

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

    • to_python: 把路径转为一个Python对象
    • to_url: 把参数转为符合URL的形式。

    我们访问两个url就可以看懂啊效果:

    1. http://127.0.0.1:9000/list2/a|b/ =效果是> Separator: | [u'a', u'b']
    2. http://127.0.0.1:9000/list1/a+b/ =效果是> Separator: + [u'a', u'b']

    HTTP方法

    HTTP 可以访问多个URL方法,默认情况下,路由只回应GET请求,但是通过app.route装饰器传递methods参数可以改变这个行为,如下所示:

    @app.route('/item/<id>/',methods=['GET','POST','DELETE'])
    

    methods里面可以写入所有HTTP的方法。
    如果存在GET,那么会自动地添加HEAD方法,无须干预,它会确保遵照HTTP RFC(描述HTTP协议的文档)处理HEAD请求,所以完全可以忽略

    唯一的URL

    Flask的URL规则基于Werkzeug的路由模块,这个模块背后的思想就是基于Apache以及更早的HTTP服务器主张,希望保证优雅且唯一的URL。
    举个例子:

    @app.route('/project/')
    def project():
        return 'THe project Page'
    

    上述看起来很像一个文件系统中的文件夹,以访问一个结尾不带斜线的URL会被重定向到带斜线的规范的URL上去,这样有助于避免搜索引擎索引到同一个页面两次。
    再看一个例子:

    @app.route('/about')
    def about():
        return "the about apge"
    

    URL结尾不带斜线的,很像文件的路径,但是访问带斜线的URL(/about/)会产生一个“Not Found” 的错误

    构造URL

    用url_for 构建URL,它接受函数名作为第一个参数,也接受对应的URL规则变量部分命名的参数,未知的变量部分会添加到URL微末作为查询参数。
    构建URL而不选择直接在代码中拼URL原因有两点:

    1. 在未来有更改的时候只需要一次性修改URL,而不用到处去替换。
    2. url构建会转义特殊字符和Unicode数据,这些工作不需要我们自己处理。

    请看例子:

    #coding:utf-8
    from flask import  Flask,url_for
    app = Flask(__name__)
    
    @app.route('/item/1/')
    def item(id):
        print('id',id)
    
    with app.test_request_context():
        print url_for('item',id='1')
        print(url_for('item',id=2,next='/'))
    
    

    test_request_context可以帮助我们在交互模式下产生请求上下文,我们运行下这个py文件,查看下结果:

    /root/venv/bin/python /root/PycharmProjects/FlaskPratice/pratice2.py
    /item/1/?id=1
    /item/1/?id=2&next=%2F
    

    跳转和重定向

    跳转(状态码301)多用于就网址在废弃前装箱新网址,以保证用户的访问,有页面被永久移走的概念。重定向(状态码302)表示页面暂时性的转移。但是也不建议经常性用重定向。在Flask里面是通过flask.rediret实现的,在django里面通过HttpRedirect实现的。

    redirect(location)   # 默认是301
    redirect(location,code=301)   # 通过code参数可以指定状态码
    

    Flask还可以支持303,305,307重定向,但是很少用到。
    基于前面所讲的内容,我们来看一个更全面的例子。
    config.py和simple.py都在同一个目录下面,
    首先看下存放配置的config:

    # coding=utf-8
    DEBUG = False
    
    try:
        from local_settings import *
    except ImportError:
        pass
    

    我们在看看主体py文件的代码

    # coding=utf-8
    from flask import Flask, request, abort, redirect, url_for
    
    app = Flask(__name__)
    app.config.from_object('config')
    
    
    @app.route('/people/')
    def people():
        name = request.args.get('name')
        if not name:
            return redirect(url_for('login'))
        user_agent = request.headers.get('User-Agent')
        return 'Name: {0}; UA: {1}'.format(name, user_agent)
    
    
    @app.route('/login/', methods=['GET', 'POST'])
    def login():
        if request.method == 'POST':
            user_id = request.headers.get('user_id')
            return 'User: {} login'.format(user_id)
        else:
            return 'Open Login page'
    
    
    @app.route('/secret/')
    def secret():
        abort(401)
        print 'This is never executed'
    
    
    if __name__ == '__main__':
        app.run(host='0.0.0.0', port=80, debug=app.debug)
    

    参数解释下:

    1. 访问/people 的请求访问跳转到/people/,保证URL的唯一性。
    2. reqeusts.headers 存放请求的头信息,通过它可以获取了UA值。
    3. request.method 的值请求的类型。
    4. 执行abort(401)会放弃请求并返回错误代码401,表示访问错误,之后的代码永远不会被执行。
    5. app.debug 就是我们在config.py里面配置的。
  • 相关阅读:
    Codeforces 876C Classroom Watch:枚举
    Codeforces 876B Divisiblity of Differences:数学【任意两数之差为k的倍数】
    BZOJ 3943 [Usaco2015 Feb]SuperBull:最大生成树
    BZOJ 3391 [Usaco2004 Dec]Tree Cutting网络破坏:dfs【无根树 节点分枝子树大小】
    markdown常用数学符号小结
    BZOJ3211花神游历各国-线段树&树状数组-(HDU4027同类型)
    一维二维树状数组写法总结
    hdu4352-XHXJ's LIS状压DP+数位DP
    常用Git命令以及出现的状况ing
    bitset简单用法
  • 原文地址:https://www.cnblogs.com/liaojiafa/p/6664501.html
Copyright © 2020-2023  润新知