Flask之路由系统,CBV与FBV,请求响应,模板语言,session使用及原理,闪现,仿中间件之扩展

一、路由系统

 1. 示例

from flask import Flask,render_template,request,redirect,session,url_for

app = Flask(__name__)


# endpoint别名,通过别名可反向生成url
# url后跟参数规则/index/<int:nid>,int需要指定,字符串可以直接使用<nid>
# 参数数据类型示例
# @app.route('/user/<username>')
# @app.route('/post/<int:post_id>')
# @app.route('/post/<float:post_id>')
# @app.route('/post/<path:path>')
# @app.route('/login', methods=['GET', 'POST'])


@app.route('/index/<int:nid>',methods=['GET',"POST"],endpoint='fff')
def index(nid):
v = url_for('fff',nid=123) # 结合endpoint,url_for反向生成url,可传参
print(v) # /index/123
return 'xxxx'


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

 2. @app.route和app.add_url_rule参数

           rule                                     URL规则
            view_func,                  视图函数名称
            defaults=None,              默认值,在路由装饰器中为视图函数预设的实参,当URL中无参数,视图函数需要参数时,使用defaults={'k':'v'}为视图函数提供参数
            endpoint=None,              名称,用于反向生成URL,即: url_for('名称')
            methods=None,               允许的请求方式,如:["GET","POST"]
            

            strict_slashes=None,        对URL最后的 / 符号是否严格要求,
                                        如:
                                            @app.route('/index',strict_slashes=False),
                                                访问 http://www.xx.com/index/ 或 http://www.xx.com/index均可
                                            @app.route('/index',strict_slashes=True)
                                                仅访问 http://www.xx.com/index 


            redirect_to=None,           重定向到指定地址
                                        如:
                                            @app.route('/index/<int:nid>', redirect_to='/home/<nid>')
                                            或
                                            def func(adapter, nid):
                                                return "/home/888"
                                            @app.route('/index/<int:nid>', redirect_to=func)


            subdomain=None,             子域名访问,不加subdomain默认为www
                                                from flask import Flask, views, url_for

                                                app = Flask(import_name=__name__)
                                                app.config['SERVER_NAME'] = 'wupeiqi.com:5000'


                                                @app.route("/", subdomain="admin")
                                                def static_index():
                                                    """Flask supports static subdomains
                                                    This is available at static.your-domain.tld"""
                                                    return "static.your-domain.tld"


                                                @app.route("/dynamic", subdomain="<username>")      # 动态接收子域名,并可传为参数
                                                def username_index(username):
                                                    """Dynamic subdomains are also supported
                                                    Try going to user1.your-domain.tld/dynamic"""
                                                    return username + ".your-domain.tld"


                                                if __name__ == '__main__':
                                                    app.run()
View Code

3. flask扩展支持正则

from flask import Flask,url_for
from werkzeug.routing import BaseConverter
app = Flask(__name__)


class RegexConverter(BaseConverter):
    """
    flask中的url所有的数据类型得有自己的对应的类
    DEFAULT_CONVERTERS = {
    'default':          UnicodeConverter,
    'string':           UnicodeConverter,
    'any':              AnyConverter,
    'path':             PathConverter,
    'int':              IntegerConverter,
    'float':            FloatConverter,
    'uuid':             UUIDConverter,
    }
    自定义URL匹配正则表达式,RegexConverter类时之拥有正则可以匹配的类,进行匹配操作
    """

    def __init__(self, map, regex):
        super(RegexConverter, self).__init__(map)
        self.regex = regex

    def to_python(self, value):
        """
        路由匹配时,匹配成功后传递给视图函数中参数的值
        :param value:
        :return:
        """
        return int(value)

    def to_url(self, value):
        """
        使用url_for反向生成URL时,传递的参数经过该方法处理,返回的值用于生成URL中的参数
        :param value:
        :return:
        """
        val = super(RegexConverter, self).to_url(value)
        return val

app.url_map.converters['regex'] = RegexConverter        # 将自定义正则匹配的类加入converters


@app.route('/index/<regex("d+"):nid>',methods=['GET',"POST"],endpoint='fff')
def index(nid):
    v = url_for('fff',nid=nid)
    print(v)                    # 输入:http://127.0.0.1:5000/index/888,输出/index/888
    return 'xxx'


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

 二、Flask的FBV与CBV

1. FBV

# 方式一
@app.route('/index/<regex("d+"):nid>',methods=['GET',"POST"],endpoint='fff')
def index(nid):
    v = url_for('fff',nid=nid)
    print(v)                    # 输入:http://127.0.0.1:5000/index/888,输出/index/888
    return 'xxx'

--------------------------------------------------------------------------------
# 方式二
def index(nid):
    v = url_for('fff',nid=nid)
    print(v)                    # 输入:http://127.0.0.1:5000/index/888,输出/index/888
    return 'xxx'

app.add_url_rule('/index',index)
View Code

2. CBV

from flask import Flask,views,url_for
app = Flask(__name__)


def auth(func):
    def wrapper(*args,**kwargs):
        print('before')
        result = func(*args,**kwargs)
        print('after')
        return result
    return wrapper

class IndexView(views.MethodView):

    methods = ["GET"]           # 相当于FBV中的@app.route('/index',methods=['GET','POST'])

    decorators = [auth,]        # 所有的方法都经过这个装饰器

    def get(self):
        v = url_for('fff')      # 配合IndexView.as_view(name='fff')使用
        print(v)
        return "GET"

    def post(self):
        return "POST"

app.add_url_rule('/index',view_func=IndexView.as_view(name='fff'),)
# name='index' 相当于FBV的endpoint使用,可反向生成url

if __name__ == '__main__':
    app.run()
View Code

 三、请求与相应

1. 请求及相应相关信息

        # 请求相关信息
        # request.method
        # request.args
        # request.form
        # request.values
        # request.cookies
        # request.headers
        # request.path
        # request.full_path
        # request.script_root
        # request.url
        # request.base_url
        # request.url_root
        # request.host_url
        # request.host
        # request.files
        # obj = request.files['the_file_name']
        # obj.save('/var/www/uploads/' + secure_filename(f.filename))

        # 响应相关信息
        # return "字符串"
        # return render_template('html模板路径',**{})
        # return redirect('/index.html')

        # response = make_response(render_template('index.html'))
        # response是flask.wrappers.Response类型
        # response.delete_cookie('key')
        # response.set_cookie('key', 'value')
        # response.headers['X-Something'] = 'A value'
        # return response
View Code

2. 示例及urlencode,unquote,quote,jsonify,make_response的使用

from flask import Flask,url_for,request,jsonify,make_response
from urllib.parse import urlencode,quote,unquote

app = Flask(__name__)

@app.route('/index',endpoint='xxx')
def index():
    # request
    # get_data = request.args             # http://127.0.0.1:5000/index?nid=1&name=eiyouwei
    # print(get_data)                     # ImmutableMultiDict([('nid', '1'), ('name', 'eiyouwei')])
    #
    # v = request.args.getlist('name')    # http://127.0.0.1:5000/index?nid=1&name=eiyouwei
    # print(v)                            # ['eiyouwei']
    #
    # 使用python模块urlencode,生成url参数
    # get_data = request.args             # http://127.0.0.1:5000/index?nid=1&name=eiyouwei
    # get_dict = get_data.to_dict()       # 将参数信息转化为字典
    # get_dict['gender'] = 'male'
    # url = urlencode(get_dict)
    # print(url)                          # nid=1&name=eiyouwei&gender=male

    # 针对中文在url参数中转化为的特殊字符的转化工具unquote,quote
    # val = request.query_string          # http://127.0.0.1:5000/index?nid=1&name=%E5%93%8E%E5%91%80%E5%91%80
    # print(val)                          # b'nid=1&name=%E5%93%8E%E5%91%80%E5%91%80'
    # print(unquote('%E5%93%8E%E5%91%80%E5%91%80'))       # 哎呀呀
    # print(quote('哎呀呀'))                              # %E5%93%8E%E5%91%80%E5%91%80



    # response
    # return jsonify(name='alxe',age='180')
    # '''
    # jsonify返回json格式的数据
    # {
    #   "age": "180",
    #   "name": "alxe"
    # }
    # '''
    response = make_response('xxx')         # make_response可以响应头等加入信息,操作
    response.headers['Olive'] = '111111'    # 给响应头加入了信息Olive:111111
    return response

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

 四、模板语言(jinjia2)

1. 视图函数

from flask import Flask,render_template,Markup

app = Flask(__name__)

def test(a1,a2):
    return a1 + a2

@app.template_global()          # 无需传参,jinjia2全局可使用
def sb(a1, a2):
    return a1 + a2


@app.template_filter()          # jinjia2简单操作即可使用
def db(a1, a2, a3):
    return a1 + a2 + a3


@app.route('/index',endpoint='xxx')
def index():
    v1 = '字符串'
    v2 = [11,22,33]
    v3 = {'k1':'v1','k2':'v2'}
    # v4 = "<input type='text'/>"
    v4 = Markup("<input type='text'/>")     # 相当于django中的mark_safe,防止跨站XXS攻击
    return render_template('index.html',v1=v1,v2=v2,v3=v3,v4=v4,test=test)

if __name__ == '__main__':
    app.run()
View Code

2. 模板语言

{% extends 'layout.html' %}
{%block body%}
    <p>{{v1}}</p>
    <ul>
        {% for item in v2 %}
        <li>{{item}}</li>
        {% endfor %}
    </ul>
    <ul>
        {% for k,v in v3.items() %} <!-- 与 django不同jinjia2需要加括号-->
            <li>{{k}}  {{v}}</li>
        {% endfor %}
    </ul>

    <p>{{v3.k1}}</p>
    <p>{{v3.get('k1')}}</p>
    <!--<p>{{v4|safe}}</p>-->
    <p>{{v4}}</p>
    <p>{{test(1,23)}}</p>
    <p>{{sb(1,2)}}</p>      <!--template_global可直接使用-->
    <p>{{1|db(2,3)}}</p>    <!--template_filter需要用管道符调用,管道符之前是第一个参数,括号中是其余的参数-->

    <!--宏,想函数一样的使用-->
    {% macro abc(name, type='text', value='') %}
        <input type="{{ type }}" name="{{ name }}" value="{{ value }}">
        <input type="{{ type }}" name="{{ name }}" value="{{ value }}">
        <input type="{{ type }}" name="{{ name }}" value="{{ value }}">
        <input type="{{ type }}" name="{{ name }}" value="{{ value }}">
    {% endmacro %}
    {{ abc('egon') }}
{%endblock%}
View Code

3. layout

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>模板</h1>
    {%block body%}{%endblock%}
</body>
</html>
View Code

五、flask-session

1. session保存的原理

session本质上操作的是字典。以字典形式保存在内存当中。

flask默认方式,程序执行过程中,若干次操作session,首先保存在内存当中。

在最后返回的前,通过cookie保存在浏览器,提升了执行效率,节省了请求的此书。

其他框架可能会操作一次session,保存一次session到如数据库中。

2. session配置的方式

flask中的配置文件是一个flask.config.Config对象(继承字典),默认配置为:
    {
        'PERMANENT_SESSION_LIFETIME':           timedelta(days=31),    # session超时时间
        'SESSION_COOKIE_NAME':                  'session',    # session名称
        'SESSION_COOKIE_DOMAIN':                None,        # session支持的域名
        'SESSION_COOKIE_PATH':                  None,
        'SESSION_COOKIE_HTTPONLY':              True,
        'SESSION_COOKIE_SECURE':                False,
        'SESSION_REFRESH_EACH_REQUEST':         True,    # 每次访问重新计算session失效时间
    }
 
 
from flask import Flask,session
 
app = Flask(__name__)
 
app.secret_key = 'adfadsfhjkhakljsdfh'
app.config['SESSION_COOKIE_NAME'] = 'session_lvjing'
 
@app.route('/index',endpoint='xxx')
def index():
    session['xxx'] = 123
    return 'xxx'
 
if __name__ == '__main__':
    app.run()
View Code

六、闪现(flash)

在session的基础上,把值放入session,取的同时将值删除(pop)。

如果普通的调用session保存传递,每次在session中都已存储了值,如果使用闪现则只会出现一次即消失。

from flask import Flask,session,flash,request,get_flashed_messages,redirect

app = Flask(__name__)

app.secret_key = 'adfadsfhjkhakljsdfh'

@app.route('/index')
def index():
    msg = get_flashed_messages()
    # msg = session.get('msg','')
    print(msg)
    return 'xxx'

@app.route('/login')
def login():
    flash('登录成功')
    # session['msg'] = 111
    return redirect('/index')

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

七、 仿中间件之扩展

扩展的默认执行顺序与django中的中间件一致,request根据先后顺序执行,response则相反,后进先出。

 1 from flask import Flask
 2 
 3 app = Flask(__name__)
 4 
 5 app.secret_key = 'adfadsfhjkhakljsdfh'
 6 
 7 
 8 # 在第一个用户访问时,执行之后不再执行,
 9 # 原理为将一个变量置为False,第一次访问时改为True,之后再次访问不再执行
10 # @app.before_first_request
11 # def process_first_request():
12 #     print('process_first_request')
13 
14 
15 @app.before_request
16 def process_request1():
17     print('process_request1')
18 
19 @app.after_request
20 def process_response1(response):     # 响应中间件需要提供response参数,及返回response参数
21     print('process_response1')
22     return response
23 
24 @app.before_request
25 def process_request2():
26     print('process_request2')
27 
28 @app.after_request
29 def process_response2(response):     # 响应中间件需要提供response参数,及返回response参数
30     print('process_response2')
31     return response
32 
33 
34 @app.route('/index')
35 def index():
36     print('aaa')
37     return 'xxx'
38 
39 
40 if __name__ == '__main__':
41     app.run()
42 
43 ------------------------------------
44 
45 process_request1
46 process_request2
47 aaa
48 process_response2
49 process_response1
View Code
原文地址:https://www.cnblogs.com/yunweixiaoxuesheng/p/8359427.html