本篇主要内容:

  闪现

  请求扩展  

  中间件  

  蓝图

写装饰器,常用 functools模块,帮助设置函数的元信息

  1. import functools
  2.  
  3. def wrapper(func):
  4. @functools.wraps(func)
  5. def inner(*args,**kwargs):
  6. return func(*args,**kwargs)
  7.  
  8. return inner
  9.  
  10. @wrapper
  11. def f1():
  12. pass
  13.  
  14. print(f1.__name__) # f1

续接第一篇

8.Flask之闪现

  1. # 首先要导入flash 和 get_flashed_messages
  2. from flask import Flask,flash,get_flashed_messages
  3. app = Flask(__name__)
  4. app.secret_key=""
  5.  
  6. @app.route("/get")
  7. def get():
  8. # 2.从某个地方获取设置过的所有值,并清除。 类似于pop
  9. # 第一次运行可以获取到所有的设置的值;第二次运行就清除掉了所有的设置的值
  10. data = get_flashed_messages()
  11. print(data)
  12. return "hello World"
  13.  
  14. @app.route("/set")
  15. def set():
  16. # 1. 向某个地方设置一个值
  17. flash("军人")
  18. return "Hello army"
  19.  
  20. if __name__=="__main__":
  21. app.run()

闪现有什么作用呢?

  1. 比如:假设在A页面做个操作,但该操作失败了,要跳转到B页面并显示这些错误信息
  1. from flask import Flask,flash,get_flashed_messages,request,redirect
  2. app = Flask(__name__)
  3. app.debug = True
  4. app.secret_key=""
  5.  
  6. @app.route("/index")
  7. def index():
  8. # get请求用request.args.get, v是接受参数的变量
  9. # 浏览器请求:
  10. val = request.args.get('v')
  11. if val =="body":
  12. return "hello World, guys"
  13. # 如果请求参数不是body,则跳转到错误页面,需要将错误信息flash,也就是设置错误值到某个地方
  14. # A.flash不分类,直接设置值
  15. flash("前端输入参数错误")
  16. # B.flash还可以对错误信息,进行分类
  17. flash("前端输入参数错误", category="x1")
  18. return redirect("/error")
  19.  
  20. @app.route("/error")
  21. def error():
  22. '''
  23. 显示错误信息
  24. '''
  25. # 跳转到error页面后,请求时获取错误信息
  26. # A.flash没有分类时
  27. # data = get_flashed_messages() # 获取的就是flash的值
  28. # B. 对于有分类的,取值时可以通过 category_filter 根据分类取错误信息
  29. data = get_flashed_messages(category_filter=['x1'])
  30. # 可能有很多的错误信息,也可以按照索引的方式取出错误值
  31. if data:
  32. msg = data[0]
  33. else:
  34. msg = "..."
  35. return "错误信息:%s" %(msg)
  36.  
  37. if __name__=="__main__":
  38. app.run()

闪现是怎么实现的呢?

其实,它就是通过session做的,先把数据存在session里,数据如果在session里,只要不删,就永远在。

然后,如果值被拿走,就会通过session.pop()的方式给拿走。

所以,就不用担心数据错乱。因为每个用户都会有自己的一个session,基于session就会把数据隔离开了。

闪现的应用:

  对临时数据操作,如:显示错误信息

9.Flask之请求扩展(类似Django中间件)--其实也是Flask的中间件

场景:

商业应用一般都要求登录后才可以进行其他操作,上一篇我们基于装饰器的方式做,但是如果函数越来越多,那就要新增一个函数,就要添加一个装饰器。

为了省事,在Django里通过中间件的方式做的,但是Flask里没有类似的中间件,就需要通过Flask里的请求扩展的方式做。

(1)做用户登录认证 before_request   —常用

示例:基于Flask的请求扩展做一个用户认证功能

  1. from flask import Flask,render_template,request,redirect,session,url_for
  2.  
  3. app = Flask(__name__)
  4. app.debug = True
  5. app.secret_key = "123#234"
  6.  
  7. USERS = {
  8. 1:{"name":"老大", "age":19,"gender":"男", "resume":"言语措辞间都能体会到今日头条的谨小慎微,生怕再出现任何问题……."},
  9. 2:{"name":"老二", "age":18,"gender":"女", "resume":"当打开这款APP之后,就会发现这跟已经“死”去的内涵段子简直是一模一样。更厉害的地方是,它还支持用用户迁移内涵段子上的内容信息。"},
  10. 3:{"name":"老三", "age":17,"gender":"男", "resume":"如果狒狒会说人话,他肯定是在说:喂…你怎么只给我吃了一口就跑了呀,我还没吃饱啊…喂喂喂…给我回来呀!哈哈哈"},
  11. }
  12.  
  13. # 基于flask里请求扩展来做
  14. @app.before_request
  15. def process_request(*args, **kwargs):
  16. # 验证表示,任何地址请求都会先执行before_request,所以登录验证就可以在before_request里做用户认证功能了
  17. print("其他请求之前就执行了process_request")
  18. # 4.访问/login的时候还没有登录,就会一直重定向到登录页,所以就要设置个白名单,如果请求地址是/login,就返回None
  19. if request.path == "/login":
  20. return None
  21. # 1.登录验证功能
  22. user = session.get('user_info')
  23. # 2.如果登录信息正常,什么都不做,程序继续其他执行
  24. if user:
  25. return None
  26. # 3.如果登录验证不通过,就重定向到登录页面
  27. return redirect("/login")
  28.  
  29. @app.route("/detail/<int:nid>", methods=['GET'])
  30. def detail(nid):
  31. detail_info = USERS.get(nid)
  32. # 如果有值,就跳到详情页
  33. return render_template("detail.html",info = detail_info)
  34.  
  35. @app.route("/index", methods=['GET'])
  36. def index():
  37. return render_template("index.html", user_dict=USERS)
  38.  
  39. @app.route("/login", methods=['GET', 'POST'], endpoint='l1')
  40. def login():
  41. if request.method =="GET":
  42. return render_template("login.html")
  43. else:
  44. user = request.form.get("username")
  45. pwd = request.form.get("password")
  46. if user == "alex" and pwd =="":
  47. session['user_info'] = user
  48. return redirect("/index")
  49. return render_template("login.html", **{"error":"用户名和密码错误"})
  50.  
  51. if __name__ == "__main__":
  52. app.run()

(2)有before_request, 就天然的有after_request —常用

  1. from flask import Flask,render_template,request,redirect,session,url_for
  2. app = Flask(__name__)
  3. app.debug = True
  4. app.secret_key = 'siuljskdjfs'
  5.  
  6. @app.before_request
  7. def process_request1(*args,**kwargs):
  8. print('process_request1 进来了')
  9.  
  10. @app.after_request
  11. def process_response1(response):
  12. print('process_response1 走了')
  13. # after_request 必须返回 response
  14. return response
  15.  
  16. # 视图函数
  17. @app.route('/index',methods=['GET'])
  18. def index():
  19. print('index函数')
  20. return "Index"
  21.  
  22. if __name__ == '__main__':
  23. app.run()

(3)请求扩展可以添加多个

  1. from flask import Flask,render_template,request,redirect,session,url_for
  2. app = Flask(__name__)
  3. app.debug = True
  4. app.secret_key = 'siuljskdjfs'
  5.  
  6. @app.before_request
  7. def process_request1(*args,**kwargs):
  8. print('process_request1 进来了')
  9. return "拦截"
  10.  
  11. @app.before_request
  12. def process_request2(*args,**kwargs):
  13. print('process_request2 进来了')
  14.  
  15. @app.after_request
  16. def process_response1(response):
  17. print('process_response1 走了')
  18. # after_request 必须返回 response
  19. return response
  20.  
  21. @app.after_request
  22. def process_response2(response):
  23. print('process_response2 走了')
  24. return response
  25.  
  26. # 视图函数
  27. @app.route('/index',methods=['GET'])
  28. def index():
  29. print('index函数')
  30. return "Index"
  31.  
  32. if __name__ == '__main__':
  33. app.run()
  34.  
  35. '''
  36. Flask请求扩展也可以写多个
  37. 但是要注意,多个请求扩展的执行顺序是有差别的:
  38. 对于before_request,是按照写的代码的顺序从上到下的顺序正序执行的
  39. 对于after_request, 是按照写的代码的顺序从下到上的顺序倒序执行的
  40.  
  41. 如果before_request return了(即程序被拦截了),其他before_request就不执行了,但是所有的after_request都会继续执行
  42. '''

(4)定制错误信息:errorhandler(404)

  1. from flask import Flask,render_template,request,redirect,session,url_for
  2. app = Flask(__name__)
  3. app.debug = True
  4. app.secret_key = 'siuljskdjfs'
  5.  
  6. # 经常会出现url不存在的情况,一般会有错误信息
  7. # 而这个错误信息也是可以进行定制的,根据错误码定制错误信息方法如下:
  8. @app.errorhandler(404)
  9. def error_404(arg):
  10. return "404错误了"
  11.  
  12. # 视图函数
  13. @app.route('/index',methods=['GET'])
  14. def index():
  15. print('index函数')
  16. return "Index"
  17.  
  18. if __name__ == '__main__':
  19. app.run()

(5)模板中定制方法(定制模板方法): template_global()  和  template_filter()

  1. from flask import Flask,request
  2. app = Flask(__name__)
  3. app.debug = True
  4.  
  5. # 这就是基于请求扩展的 定制模板方法
    # 相对于在模板里定制了一个函数
  6. @app.template_global()
  7. def sb(a1, a2):
  8. return a1 + a2
  9.  
  10. if __name__ == '__main__':
  11. app.run()
  12.  
  13. #在HTML里调用的方式如下:
  14. {{sb(1,2)}}
  1. from flask import Flask,request
  2. app = Flask(__name__)
  3. app.debug = True
  4.  
  5. # 这就是基于请求扩展的 定制模板方法
  6. @app.template_filter()
  7. def db(a1, a2, a3):
  8. return a1 + a2 + a3
  9.  
  10. if __name__ == '__main__':
  11. app.run()
  12.  
  13. #在HTML里调用的方式如下:
  14. {{ 1|db(2,3)} # 参数 a1 = 1,是第一个参数; a2=2 是第二个参数; a3=3 是第三个参数

(6)只有第一次请求才执行的:before_first_request

  比如:数据库的连接,初始化操作

  1. from flask import Flask,request
  2. app = Flask(__name__)
  3. app.debug = True
  4.  
  5. # 内部其实就有个判断,初始值是FALSE,第一次执行后将值改变为True,以后判断后就不执行了
  6. @app.before_first_request
  7. def before_first_request2():
  8. print('before_first_request2')
  9.  
  10. if __name__ == '__main__':
  11. app.run()

10. 中间件

前面关于请求的中间件已经在请求扩展里讲了。

由于知道请求之前会执行一个wsgi_app,所以这里做个请求之前的定制,先了解一下

  1. from flask import Flask
  2. app = Flask(__name__)
  3.  
  4. @app.route("/login", methods=['GET', 'POST'])
  5. def index():
  6. pass
  7.  
  8. class Md(object):
  9. def __init__(self, old_wsgi_app):
  10. self.old_wsgi_app = old_wsgi_app
  11.  
  12. def __call__(self, environ, start_response):
  13. print("开始之前")
  14. ret = self.old_wsgi_app(environ, start_response)
  15. print("结束之后")
  16. return ret
  17.  
  18. if __name__ =="__main__":
  19. app.wsgi_app = Md(app.wsgi_app) # 相当于把wsgi_app给更新了
  20. app.run()

11.蓝图

前置情景:一个项目一般会有多个.py文件组成,这些.py文件分别执行不同的功能,那就可以为这些不同功能的.py文件给划分到不同的目录里去。

所以蓝图用于为应用提供目录划分:

未使用蓝图的目录结构,但是没有Flask提供的蓝图好,蓝图里还提供了一些类似请求扩展的东西等等。

使用蓝图的目录结构

           

使用蓝图的目标:

1. 构造程序目录

2. 自定义程序目录

  批量处理url

  定制模板路径和静态文件路径

  请求扩展:

    - 可以针对app, 即全部程序都生效

    - 也可以针对单个的蓝图,即只有在执行该蓝图时,请求扩展才会生效

Flask的官方文档可知,蓝图需要掌握的几个方面知识点如下:

1. 注册蓝图

2. 蓝图资源

3. 静态文件

4. 模板

5. 构造URL

第二篇 Flask基础篇之(闪现,蓝图,请求扩展,中间件)的更多相关文章

  1. 第一篇 Flask基础篇之(配置文件,路由系统,模板,请求响应,session&cookie)

    Flask是一个基于Python开发并且依赖jinja2模板和Werkzeug WSGI服务的一个微型框架,对于Werkzeug本质是Socket服务端,其用于接收http请求并对请求进行预处理,然后 ...

  2. Flask的闪现(message) 请求扩展 中间件 蓝图

    补充:一个编程思路 需求:做一些邮件短信微信的消息通知,比如账单告警之类的:比如数据库操作,数据库种类繁多:缓存的选择比如redis/memcache,诸如此类需要进行选择配置,如果我们单纯的用函数去 ...

  3. Flask - 请求响应 | session | 闪现 | 请求扩展 | 中间件

    请求响应 flask的请求信息都在request里 flask的响应方式有四剑客,也可以自定义响应 请求相关信息 # request.method 提交的方法 # request.args get请求 ...

  4. session、闪现、请求扩展

    session 除请求对象之外,还有一个session对象.它允许你在不同请求储存特定用户的信息.它是在Cookies的基础上实现的,并且对,Cookies进行密钥签名要使用会话,你需要设置一个密钥. ...

  5. python框架之Flask基础篇(四)-------- 其他操作

    1.蓝图 要用蓝图管理项目,需要导入的包是:from flask import Buleprint 具体大致分为三步: 1.先在子模块中导入蓝图包,然后再创建蓝图对象. 2.然后将子模块中的视图函数存 ...

  6. python之路第二篇(基础篇)

    入门知识: 一.关于作用域: 对于变量的作用域,执行声明并在内存中存在,该变量就可以在下面的代码中使用. if 10 == 10: name = 'allen' print name 以下结论对吗? ...

  7. python框架之Flask基础篇(一)

    一.第一个hello world程序 # coding=utf-8 from flask import Flask app = Flask(__name__) @app.route('/') def ...

  8. python框架之Flask基础篇(三)-------- 模版的操作

    1.flask特有的变量和函数: 变量:g.session.request.config 函数:url_for().get_flashed_messages()这个函数注意了啊,记住这是个函数,别忘了 ...

  9. python框架之Flask基础篇(二)-------- 数据库的操作

    1.flask连接数据库的四步: 倒入第三方数据库扩展包:from flask_sqlalchemy import SQLAlchemy 配置config属性,连接数据库: app.config[&q ...

随机推荐

  1. CPP-基础:信号量

    windows api 多线程---信号量 信号量(Semaphore)和互斥量一样,属于内核对象.它自动执行可用资源查询的测试,如果有可用资源,则可用资源的计数减少1,从而避免其它线程请求资源.当该 ...

  2. 十三、IntelliJ IDEA 中的版本控制介绍(下)

    我们已经简单了解了 IntelliJ IDEA 的版本控制机制,那么接下来,就让我们一起看看在 IntelliJ IDEA 中进行具体的版本控制操作. 标注1:Checkout from Versio ...

  3. ARP, Fragmentation and Reassembly

    Address Resolution Protocol IP addresses are said to be logical, because they are defined in terms o ...

  4. 【AngularJS学习笔记】Java Script "use strict" 严格模式

    ---恢复内容开始--- 学习Angular的时候,发现好多优秀的源码中,JS文件的最上面,都会写上"use strict"; 这几个字符,搜了一下,找到一篇比较不错的文章,抄过来 ...

  5. 使用jenkins配置.net mvc5网站自动构建全过程记录

    持续集成是个简单重复劳动,人来操作费时费力,使用自动化构建工具完成是最好不过的了.最终可以实现的一个效果是,svn提交代码,服务器端自动编译并发布. 所使用的版本:windows server 200 ...

  6. 关于swing界面label和button的动态设置文字

    在引入发送验证码功能后,想让button的文本动态变化,发现如下方法并不能做到: int limitSec=10; while(limitSec>0){ sendyzhm.setEnabled( ...

  7. File常见操作函数

    String Name = File.getName();  //获得文件或文件夹的名称: String parentPath = File.getParent();  //获得文件或文件夹的父目录 ...

  8. Python 学习笔记(十一)Python语句(一)

    运算符和条件语句 算术运算符 运算符 描述 实例 + 加 - 两个对象相加 a + b 输出结果 30 - 减 - 得到负数或是一个数减去另一个数 a - b 输出结果 -10 * 乘 - 两个数相乘 ...

  9. sql中UNION和UNION ALL的区别

    写sql时我们经常会遇到需要把从多张表查询的集果集进行合并.这时就用到了union.使用union或union all 时一定要保证查询的列的一致性 .不然sql会报错.字段不一致的话可以用单引号来占 ...

  10. [译文][转载]greenlet:轻量级并发程序

    英文原文地址:https://greenlet.readthedocs.io/en/latest/中文翻译转载地址:https://zhuanlan.zhihu.com/p/25188731 背景 g ...