自定义路由正则匹配、模板语法、请求响应、路由其他参数、session使用、闪现、before_request、中间件

自定义路由正则匹配:
# 添加到flask中
# 我们要用自定义的路由,用正则的话
# 1导入from werkzeug.routing import BaseConverter
# 2我先要写一个类,然后继承BaseConverter,然后实现进行初始化,to_python(self, value),to_url(self, value)
# 3 app.url_map.converters['regex1'] = RegexConverter
# 4 我们在路由里面@app.route('/index/<regex1("\d+"):nid>'),regex1='谁便,regex1("正则表达式")
# 5 regex1("正则表达式")匹配出来的结果,返回to_python,一定要return
# 6 当我们做反向解析的解析的时候,我们的参数,会传递给to_url,return的结果才是我们拼接到我们路由上
from flask import Flask, views, url_for
from werkzeug.routing import BaseConverter

app = Flask(import_name=__name__)


class RegexConverter(BaseConverter):
    """
    自定义URL匹配正则表达式
    """

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

    def to_python(self, value):
        """
        路由匹配时,匹配成功后传递给视图函数中参数的值
        """
        # value就正则匹配出来的结果
        print('value:', value, type(value))
        return "asdasdasd"

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


app.url_map.converters['regex1'] = RegexConverter

@app.route('/index/<regex1("\d+"):nid>', endpoint="sb")
def index(nid):
    print("nid", nid, type(nid))
    print(url_for('sb', nid='666'))  # /index/666

    return 'Index'


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

模板语法:

'''
jinjia2模板语言
-前端:支持函数加括号并且传参 {{ func(1,2,3) | safe}}
-其他的用法完全同DTL
-后台:视图函数用 aa=Markup(a)
-jinjia2有没有处理xss攻击?
- html中的特殊符号
'''
from flask import Flask, url_for, render_template, Markup

app = Flask(__name__)


@app.route('/')
def index():
    # def func(a, b, c):
    #     return 'sb', a + b + c
    a = "<input type='text' value='sb'>"
    a = Markup(a)  # 后台转义标签
    return render_template('index.html', func=a)  # 函数作为值传参,前端函数还可以携带参数


if __name__ == '__main__':
    app.run(port=8000)
    # 这里run本质上就是run_simple

请求响应:

from flask import Flask, render_template, request, make_response

app = Flask(__name__)
app.debug = True


@app.route('/', methods=['GET', 'POST'])
def index():
    # print(request.args.get('id'))   # get请求取值
    # print(request.form.get('name'))  # post请求取值
    # request.values  post和get提交的数据总和
    # request.cookies  客户端所带的cookie
    # request.headers  请求头
    # request.script_root
    # request.url           带域名带参数的请求路径
    # request.base_url      带域名请求路径
    # request.url_root      域名
    # request.host_url      域名
    # request.host          127.0.0.1:500
    # request.files
    # request.files        文件
    # obj = request.files['the_file_name']
    # obj.save('/var/www/uploads/' + secure_filename(f.filename))   # 存入文件

    print(request.method)  # 请求方法
    print(request.path)  # 请求路径(根路径)
    print(request.full_path)  # 请求路径携带参数路径(全路径)
    obj = make_response('你大爷的!')  # 只是把值进行封装
    obj.set_cookie('key', '1456sxxxxxxxsss')  # 往前端传送设置cookie键值对
    obj.delete_cookie('key')  # 删除掉cookie
    obj.headers['xxxx'] = 'yyyyyyyy'  # 响应头
    return obj


if __name__ == '__main__':
    app.run(port=8000)
    # 这里run本质上就是run_simple

路由的其他参数和使用:

# app.add_url_rule("/", view_func=UserView.as_view(name="user"))
# rule, URL规则
# view_func, 视图函数名称
# 为函数提供参数
# endpoint = None, 名称,用于反向生成URL,即: url_for('名称')
# methods = None, 允许的请求方式,如:["GET", "POST"]
# defaults = None, 默认值, 当URL中无参数,函数需要参数时,使用defaults = {'k': 'v'}
# #对URL最后的 / 符号是否严格要求
# strict_slashes = None
#     '''
#         @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,

from flask import Flask, redirect, render_template, jsonify, views

app = Flask(__name__)


# strict_slashes,该参数是用来设置,我们的路由是否为严格模式,False是非严格模式,True严格,默认是严格
@app.route("/index", strict_slashes=True, redirect_to="/login")
def index():
    return "ok"


@app.route("/login")
def login():
    return "sb"


@app.route("/detail/<int:nid>")
def detail(nid):
    print(nid)
    return "ok"


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

session的使用

"""
session:
-使用必须先设置一下秘钥:app.secret_key = 'nimaipaffsf'
-session['name']='kevin'存值放前端,取值 session['name']) # 取值的时候,把前端cookie通过解密,获取得到
-源码流程:
-save_session
-响应的时候,把session中的值解密序列化放到了cookie中,返回浏览器
-open_session
-请求来了,从cookie中取出来,反解,生成session对象,以后在视图函数中直接用session就可以
"""
from flask import Flask, session

app = Flask(__name__)
app.secret_key = '你打卖批'
app.debug = True


# app.config['SESSION_COOKIE_NAME'] = 'dsb'

@app.route('/', methods=['GET', 'POST'])
def index():
    session['name'] = 'kevin'
    return 'index'


@app.route('/test', methods=['GET', 'POST'])
def test():
    print(session['name'])  # 取值的时候,把前端cookie通过解密,获取得到
    return 'test'


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

闪现

"""
什么是闪现:
    a产生信息,传给c页面
    但是用户访问a页面以后,不是直接跳转到c,而是到b,或者是其它页面,但是用户访问c页面的时候,a给我的信息能拿到
"""
from flask import Flask, flash, get_flashed_messages, request

app = Flask(__name__)
app.secret_key = 'adsfsfsdgfsg'

# 1.如果要用flash就必须设置app.secret_key = 'adsfsfsdgfsg'
# 2.闪现设置好的值,只能去一次,如果再次刷新页面就取不到
# 3.我们可以通过  flash('普通信息',category="info"),对信息做分类
# 4.我们设置闪现,category_filter=("error",)进行分类信息的过滤,筛选
# 5.with_categories=True,是将显示信息把分类显示
@app.route('/index')
def index():
    flash('超时信息', category='error')
    flash('普通信息', category='info')
    return 'sffsfsfffsffsdfds'


@app.route('/error1')
def error1():
    return '错误1'


@app.route('/error2')
def error2():
    data = get_flashed_messages(with_categories=True,category_filter=('error', 'info'))
    data1 = get_flashed_messages(with_categories=True, category_filter=('error', 'info'))
    print(data, data1)
    print(data, data1)
    return '错误2'


if __name__ == '__main__':
    app.run()
before_request和after_request
from flask import Flask, request, render_template

app = Flask(__name__)

'''@app.before_request在请求进入视图函数之前执行'''
# @app.before_request
# def befor1():
#     print(request)
#     print("我是请求之前1")
#     return "123"
#
#
# @app.before_request
# def befor2():
#     print("我是请求之前2")


'''@app.after_request:在视图函数响应之后执行,但是必须接受参数response,并返回它'''
# @app.after_request
# def after1(response):
#     print("我是请求之后1")
#     return response
#
# @app.after_request
# def after2(response):
#     print("我是请求之后2")
#     return response
"""before_first_request:只执行一次,第一次请求之前,第二次请求不执行"""
@app.before_first_request
def before_first():
    print("123")

# 如论有没有异常都会执行,如果没有异常这个参数就是None,有就记录这个异常
# @app.teardown_request
# def tear(e):
#     print('teardown_request')
#     print(e)

# 捕获异常,如果出现异常,而且状态就是@app.errorhandler(404),
# @app.errorhandler(404)
# def error_404(arg):
#     print(arg)
#     return "404错误了"


# @app.errorhandler(500)
# def error(arg):
#     print(arg)
#     return "500错误了"

"""@app.template_global():设置全局函数,可以传进前端{{ sb(1,2)}}"""
# @app.template_global()
# def sb(a1, a2):
#     return a1 + a2

# 也是一种函数传参方式{{1|db(2,3)}}
# @app.template_filter()
# def db(a1, a2, a3):
#     print(a1, a2, a3)
#     return a1 + a2 + a3


@app.route('/index')
def index():
    print("我是真的视图")
    return render_template("index.html")


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

中间件:


from flask import Flask

app = Flask(__name__)
app.secret_key = 'jhfksfhsdfsd'
app.debug = True
"""
中间件:跟django中的中间件不一样
    -flask中一旦请求到来,要执行app()---->执行的是app.__call__,整个flask的入口(call在实例化对象中会走,对象的属性存在call方法里)
"""


class MyMiddleware:
    def __init__(self, my_wsgi_app):
        self.wsgi_app = my_wsgi_app   # 进行初始化

    def __call__(self, environ, start_response):
        print("之前")
        obj = self.wsgi_app(environ, start_response)
        print("之后")
        return obj


@app.route('/index')
def index():
    return "ok"


if __name__ == '__main__':
    # app.__call__
    app.wsgi_app = MyMiddleware(app.wsgi_app)

    app.run()
    # 请求来了,执行__call__本质是执行self.wsgi_app(environ, start_response),
    # MyMiddleware(app.wsgi_app)app.wsgi_app本质就是flask最终执行的方法,然后传参进去,走call方法,把执行后的结果返回出来

 

 
posted @ 2019-11-12 21:13  凯帅  阅读(796)  评论(0编辑  收藏  举报