模板
比django中多可以加括号,执行函数,传参数
from flask import Flask,render_template,Markup,jsonify,make_response app = Flask(__name__) def func1(arg): return Markup("<input type='text' value='%s' />" %(arg,)) @app.route('/') def index(): return render_template('index.html',ff = func1) if __name__ == '__main__': app.run()
index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> {{ff('六五')}} {{ff('六五')|safe}} </body> </html>
注意:
1.Markup等价django的mark_safe ,
jinga2 模板语言
-支持函数加括号并且传参 -其它的用法完全同DTL -模板中处理:{{ss|safe}} -视图函数中用 ss=Markup(ss) -有没有处理xss攻击?处理了 -处理xss攻击 -html中的特殊符号
请求响应
from flask import Flask from flask import request from flask import render_template from flask import redirect from flask import make_response app = Flask(__name__) @app.route('/login.html', methods=['GET', "POST"]) def login(): # 请求相关信息 # request.method # request.args:get形式提交的参数 # request.form:post形式提交的参数 # 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') #return jsonify({'k1':'v1'}) # 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 return "内容" if __name__ == '__main__': app.run()
session
除请求对象之外,还有一个 session 对象。它允许你在不同请求间存储特定用户的信息。它是在 Cookies 的基础上实现的,并且对 Cookies 进行密钥签名要使用会话,你需要设置一个密钥。 (app.session_interface对象)
设置:session['username'] = 'xxx' 删除:session.pop('username', None)
使用必须先设置一下秘钥:app.secret_key='assasadw' session['name']='yzy'放值,取值session['name'] 源码执行流程 --save_session --响应的时候,把session中的值加密序列化放到cookie中,返回给浏览器 --open_session --请求来了,从cookie中取出值,反解,生成session对象,以后在视图函数中直接用session就可以了 --session.modified
闪现
-设置:flash('aaa') -取值:get_flashed_message() -假设在a页面操作出错,跳转到b页面,在b页面显示a页面的错误信息
示例:
from flask import Flask,flash,get_flashed_messages,request,redirect app = Flask(__name__) app.secret_key = 'asdfasdf' @app.route('/index') def index(): # 从某个地方获取设置过的所有值,并清除。 val = request.args.get('v') if val == 'oldboy': return 'Hello World!' flash('超时错误',category="x1") return "ssdsdsdfsd" # return redirect('/error') @app.route('/error') def error(): """ 展示错误信息 :return: """ data = get_flashed_messages(category_filter=['x1']) if data: msg = data[0] else: msg = "..." return "错误信息:%s" %(msg,) if __name__ == '__main__': app.run()
''' 闪现 --使用 --设置值 flash('我出错了') flash('超时错误',category='x1') --取值:一旦去过一次,再另一个视图函数中再取就没有了 get_flashed_messages() get_flashed_messages(category_filter=['x1','x2']) --使用场景: --在某个位置放一个值,过会再去取出来 '''
请求扩展
1 before_request
类比django中间件中的process_request,在请求收到之前绑定一个函数做一些事
#基于它做用户登录认证 @app.before_request def process_request(*args,**kwargs): if request.path == '/login': return None user = session.get('user_info') if user: return None return redirect('/login')
-before_request @app.before_request def before_request(): print('来了')
类比django中间件中的process_response,每一个请求之后绑定一个函数,如果请求没有异常
@app.after_request def process_response1(response): print('process_response1 走了') return response
-afer_request @app.after_request def after_request(response): print(type(response)) print('走了了') return response
@app.before_first_request def first(): print('我的第一次')
每一个请求之后绑定一个函数,即使遇到了异常
@app.teardown_request def ter(e): print(e) print('无论如何都会走,即便出了异常')
5 errorhandler
路径不存在时404,服务器内部错误500
@app.errorhandler(404) def error_404(arg): return "404错误了"
6 template_global
@app.template_glob #标签 def sb(a1, a2): return a1 + a2 #{{sb(1,2)}}
7 template_filter
过滤器
@app.template_filter() def db(a1, a2, a3): return a1 + a2 + a3 #{{ 1|db(2,3)}}
总结:
1 重点掌握before_request和after_request,
2 注意有多个的情况,执行顺序
-flask中一旦请求到来,要执行app()---->执行的是app.__call__,整个flask的入口
-代码实现(了解)
from flask import Flask,session,url_for,redirect,request,flash,get_flashed_messages,render_template app = Flask(__name__) 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('/',methods=['GET','POST']) def index(): return 'ok' if __name__ == '__main__': app.__call__ # app.run() app.wsgi_app = MyMiddleWare(app.wsgi_app) app.run() #请求来了,执行app.__call__本质执行的是:self.wsgi_app(environ, start_response),app.wsgi_app(environ, start_response), # 会调到自己写的类的__call__方法
蓝图
对程序进行目录结构划分
目录结构:
-templates -views -__init__.py -user.py -order.py -app.py
app.py
from views import app if __name__ == '__main__': app.run()
init.py
from flask import Flask,request app = Flask(__name__) #不导入这个不行 from . import account from . import order from . import user
user.py
from . import app @app.route('/user') def user(): return 'user'
order.py
from . import app @app.route('/order') def order(): return 'order'
目录结构:
-flask_pro -flask_test -__init__.py -static -templates -views -order.py -user.py -manage.py
from flask import Flask app=Flask(__name__) from flask_test.views import user from flask_test.views import order app.register_blueprint(user.us) app.register_blueprint(order.ord)
manage.py
from flask_test import app if __name__ == '__main__': app.run(port=8008)
user.py
from flask import Blueprint us=Blueprint('user',__name__) @us.route('/login') def login(): return 'login'
order.py
from flask import Blueprint ord=Blueprint('order',__name__) @ord.route('/test') def test(): return 'order test'
-使用蓝图划分文件目录 0 生成蓝图对象 admin = Blueprint( 'admin', __name__, template_folder='templates', static_folder='static' ) 1 注册蓝图 -url_prefix访问路由的前缀 app.register_blueprint(admin, url_prefix='/admin') 2 使用(只在当前蓝图下有效) -注册路由 @admin.route('/index') -请求扩展相关 @admin.before_request
第一阶段:将ctx(request,session)放到Local对象上 第二阶段:视图函数导入:request/session request.method -LocalProxy对象.method,执行getattr方法,getattr(self._get_current_object(), name) -self._get_current_object()返回return self.__local(),self.__local(),在LocakProxy实例化的时候,object.__setattr__(self, '_LocalProxy__local', local),此处local就是:partial(_lookup_req_object, 'request') -def _lookup_req_object(name): top = _request_ctx_stack.top #_request_ctx_stack 就是LocalStack()对象,top方法把ctx取出来 if top is None: raise RuntimeError(_request_ctx_err_msg) return getattr(top, name)#获取ctx中的request或session对象 第三阶段:请求处理完毕 - 获取session并保存到cookie - 将ctx删除