一、蓝图–blueprint
类似于django中的app子应用。
flask中,要将项目模块化,就应该使用blueprint,它是flask自带的一种开发模式,目的是方便开发大型的项目。
使用
from flask import Flask,Blueprint
# 实例化一个蓝图对象
# 参数:第一个
bp = Blueprint('goods',__name__)
@bp.route('/index/')
def index():
return 'index'
if __name__ == '__main__':
app = Flask(__name__)
app.config['DEBUG'] = True
app.register_blueprint(bp,url_prefix='/goods')
app.run()
一个项目中多个蓝图
使用蓝图整合项目
二、请求钩子
类似于Django中的中间件。
用来干预请求与相应,flask中提供了四个方法
- before_first_request
- 请求到达视图之前,项目被启动之后,第一个请求达到时执行
- before_request
- 请求到达视图之前,每次请求到达时执行
- after_request
- 在每次请求之后被执行
- 接收参数:视图处理之后返回的响应
- teardown_request
- 在每次请求之后执行
- 接收参数:错误信息
flask中使用钩子,需要使用装饰器
from flask import Flask,request
app = Flask(__name__)
# 当第一个请求到达的时候执行
@app.before_first_request
def demo01():
# 可以做一些项目的初始化配置
print('before_first_request')
@app.before_request
def demo02():
# 可以获取用户信息
print('before_request')
user_id = request.args.get('id')
if not user_id:
return '缺少请求信息'
@app.after_request
def demo03(response):
# 构建返回数据的结构
print('after_request')
return response
@app.teardown_request
def demo4(response):
print(response)
print('teardown_request')
@app.route('/index/')
def index():
1/0
return 'index'
if __name__ == '__main__':
app.run()
三、上下文
程序中,根据已经写完的代码,以及即将要完成的代码,决定当前时刻要完成的或者是要使用的变量和方法。
flask当中:
请求上下文
- request 包含了请求中所有的请求信息
- session 请求中的session
应用上下文
指的是当前的app
-
g对象
-
类似于全局变量
from flask import Blueprint,request,g g_views = Blueprint('goods_views',__name__) @g_views.before_request def demo01(): username = request.args.get('username') g.username = username def outer(func): def inner(): user_id = 1 g.user_id = user_id return func() return inner @g_views.route('/index/') @outer def index(): user_id = g.user_id username = g.username print(user_id) print(username) # mymd5() return 'goods views index'
-
-
current_app
-
代理人
-
经常用在多蓝图,多视图,多模块的编程中
-
当某一些模块需要使用app的功能,但不方便直接拿到app时,就需要代理人
from flask import Blueprint,request,current_app g_views = Blueprint('goods_views',__name__) @g_views.route('/index/') def index(): mymd5() return 'goods views index' def mymd5(): # 从app的配置文件中取密钥 # 第一种 导入app 从app中获取配置信息 # app.config['SECRET_KEY'] # 第二种 利用应用上下文 config = current_app.config value = config.get("SECRET_KEY") print(value) return '加密后结果'
-
四、单元测试
将一个功能的最小模块进行测试
测试目的:是否满足预期
登录功能:
- 用户输入的用户民,类型,长度,是否为空
- 测试根据用户查询到的结果是否满足预期
单元测试,需要程序员自己编写
断言:assert
如果assert后面的表达式是一个True,表示断言成功,如果为一个False,断言失败,抛出异常
单元测试在python中,用到unittest模块(单例模式)
import unittest
class MyTest(unittest.TestCase):
def setUp(self):
'''
在测试前执行,用来加载和准备测试参数
'''
self.a = 10
self.b = 11
# 需要写测试代码
# 测试方法必须的要求 名以text_开头
def test_demo(self):
self.assertEquals(self.a,self.b,msg='a 和 b不相等')
def test_demo_has_id(self):
pass
def tearDown(self):
'''
在测试执行之后,用于回收测试环境
'''
pass
if __name__ == '__main__':
unittest.main() # 启动测试
flask
视图
@main.route('/mytest/')def mytest(): id = request.args.get('id') result = {'code':10000,'msg':'success'} if id: result['data'] = 'asdklasjdkl' return jsonify(result)
测试类
import unittest
# 导入create这个工厂方法
from app import create
from settings import Config
import json
class TestMytest(unittest.TestCase):
def setUp(self):
self.app = create(Config)
self.client = self.app.test_client() # 属于flask提供的测试方法
def test_has_id(self):
# 给mytest这个路由,发出get请求,传递id参数
# 拿到返回值
# 判断返回值是否满足我们的预期
# 发送get请求,使用urllib和request发送请求,必须保证flask服务是开启的
# 还可以使用flask提供的方法进行get,post,put,delete请求,不需要开启flask服务
response = self.client.get('/mytest/?id=1')
# 首先应该看一下,响应码是否为200,即是否请求成功
self.assertEquals(response.status_code,200)
# 判断返回值,是否符合预期
result_data = response.data # 返回的结果
result_data = result_data.decode()
data = json.loads(result_data)
# 判断返回值中是否有data
self.assertIn('data',data)
# 判断返回值中code是否为10000
self.assertEquals(data['code'],10000)
def test_no_id(self):
pass
def tearDown(self):
pass
if __name__ == '__main__':
unittest.main()
django
视图
def mytest(request):
id = request.GET.get('id')
result = {'code': 10000, 'msg': 'success'}
if id:
result['data'] = 'asdklasjdkl'
return JsonResponse(result)