python 初步认识Flask

时间:2022-07-08 00:18:27
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)