自定义路由正则匹配、模板语法、请求响应、路由其他参数、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方法,把执行后的结果返回出来