1.简介 flask 问题一: 访问百度的流程? a. 客户端: 发送请求报文, 请求行, 请求头, 请求体 b.服务端: 解析请求的报文, 解析域名, 进行路由匹配分发找到对应的视图函数, 打包, 会送给客户端, 响应头, 响应体, 响应 c.客户端: 收到了响应报文, 进行解析, 显示到浏览器中 2.框架: 定义: 封装一些方法函数的代码 框架的核心: jinja2(模板引擎), werkzeug(路由) 3.虚拟环境 思考: 为什么搭建虚拟环境? 实际开发中, 为了不影响两个项目的正常运行, 所以使用虚拟环境. 如何创建虚拟环境? mkvirtualenv 虚拟环境名称 进入虚拟环境? workon 虚拟环境名称 退出虚拟环境 deactivate 4.第一个程序helloworld 实现步骤 a. 导入模块flask b.创建实例对象 c.视图函数 d.绑定路由, 与视图函数建立联系 e.调用run方法 demo1 hello world from flask import Flask # 导入该模块 app = Flask(__name__, static_path = "/static", # 静态访问路径 static_url_path = "/static", # 静态访问路径 static_folder = "", # 静态访问文件 template_folder = "" # 模板访问的文件夹 ) # 创建实例对象 @app.route("/") def index(): return " hello world " # 定义视图函数, 与路由进行关联 if __name__ = "__main__": app.run() # 调用run方法, 运行函数 加载调试的三种方式: 记住在实例对象的下面进行配置 # 1. 通过对象来配置 class Config(object): debug = True # 进行关联 实例对象.config.form_object(Config) # 2. 通过文件来配置 实例对象.config.from_pyfile("config.ini") # 3. 通过环境变量来配置 实例对象.config.from_envvar("ENVCONFIG") 一些常用的可以直接在实例对象后创建: 实例对象.debug = True 实例对象.config["DEBUG"] = True 注意: 调用run方法是可以传递参数 实例对象.run(host, post, debug) 5.怎样设置路由? demo1 # 实现路由, 指定路径为/index @app.route("/index") def index(): return index 装饰器传参 # 传参实例 注意: 路由传递参数时, 默认会传递string类型, 也可以指定其他类型 @app.route("/user/<user_id>") def user_info(): return "%s" % user_id 思考: 如何指定一个请求方式? 通过methods来进行指定请求方式, 默认是get请求 @app.route("/index", methods=["POST","GET"]) def index(): return "index" 扩展: put: 修改服务器数据 pash: 修改服务器数据 两个之间的区别: put其中一个修改之后全部发送, pash就是传输修改的内容 delete: 删除服务器数据 option: 只需要返回HEAD, 不返回header 6.视图常用逻辑 a.返回json数据 b.重定向: url_for 注意: 如果返回的是一个固定的网址, 可以不适应url_for c.自定义状态码 #demo from flask import Flask, jsonify from flask import json from flask import redirect from flask import request from flask import url_for app = Flask(__name__) @app.route("/") def index(): return "index" @app.route("/demo1") def demo1(): return "demo1" # 给路由添加参数,格式就是 <参数名> # 并且视图函数需要接收这个参数 @app.route("/user/<int:user_id>") def demo2(user_id): return "demo2 %s" % user_id @app.route("/demo3", methods=["POST","GET"]) def demo3(): return "demo3 %s " % request.method @app.route("/json") def demo4(): json_dict = { "name": "laowang", "age" : 18 } # 使用JSON.dumps将字典转成JSON字符串 # result = json.dumps(json_dict) # return result # 使用JSON将字符串转成JSON.dumps字典 # result = json.loads(json_dict) # return result # jsonify会指定响应内容的数据格式(告诉客户端我返回给你的数据格式是什么) return jsonify(json_dict) @app.route('/redirect') def demo5(): # 重定向回到自己的页面 # url_for:取到指定视图函数所对应的路由URL,并且可以携带参数 # return redirect(url_for('demo2',user_id=123)) # 重定向到百度, 这个时候就不用书写url_for return redirect('http://www.baidu.com') @app.route('/demo6') def demo6(): return "demo6", 3456 # 3456 if __name__ == '__main__': app.run(port=1245, debug=True) 7.正则匹配路由 代码实现步骤 #导入werkzeug.routing中的BaseConverter from werkzeug.routing import BaseConverter from flask import Flask #自定义转换器 # 自定义正则转换器 class RegexConverter(BaseConverter): def __init__(self, url_map, *args): super(RegexConverter, self).__init__(url_map) # 将接受的第1个参数当作匹配规则进行保存 self.regex = args[0] # 添加转换器到默认的转换器字典中,并指定转换器使用时名字为: re app = Flask(__name__) # 将自定义转换器添加到转换器字典中,并指定转换器使用时名字为: re app.url_map.converters['re'] = RegexConverter #使用转换器去实现自定义匹配规则 #当前此处定义的规则是:3位数字 @app.route('/user/<re("[0-9]{3}"):user_id>') def user_info(user_id): return "user_id 为 %s" % user_id to_python 和 to_url class ListConverter(BaseConverter): # 自己定义转换器 regex = "(\\d+,?)+\\d$" def to_python(self, value): """当屁配到参数, 对参数进一步处理, 返回给试图函数""" return value.split(",") def to_url(self, value): """使用url_for的时候,对视图函数传的参数进行处理,处理完毕之后以便能够进行路由匹配""" result = ','.join(str(v) for v in value) return result 系统自带的转换器6种 DEFAULT_CONVERTERS = { 'default': UnicodeConverter, 'string': UnicodeConverter, 'any': AnyConverter, 'path': PathConverter, 'int': IntegerConverter, 'float': FloatConverter, 'uuid': UUIDConverter, } 8.异常捕获 a. 主动抛出异常 abort(状态码) b. errorhandler装饰器进行装饰 demo from flask import Flask from flask import abort app = Flask(__name__) @app.route('/') def index(): return 'index' @app.route('/demo1') def demo1(): # abort(404) # 注意报错码此时应该注意传入参数 a = 0 b = b / a return "demo1" @app.errorhandler(404) def page_not_found(error): return "亲, 页面不见了" @app.errorhandler(ZeroDivisionError) def zero_division_error(error): # 必须要传入一个参数 return '除数不能为0' if __name__ == '__main__': app.run(port=1111, debug=True) 9.钩子函数 demo1 from flask import Flask app = Flask(__name__) @app.before_first_request def before_first_request(response): """第一次会访问该函数并且函数里面接受一个参数:响应,还需要将响应进行返回""" print('before_first_request') return response @app.before_request def before_request(): """每次请求之前都会调用""" print('before_request') @app.teardown_request def teardown_request(error): """在请求之后会执行,如果请求的函数报有异常,会把具体异常传入到此函数""" print("teardown_request") @app.route('/') def index(): return 'index' if __name__ == '__main__': app.run(port=1456)