• flask1 未整理


    flask 扩展组件地址: flask.pocoo.org/extensions/
    flask最牛逼的地方 有别于其他框架的是 他做了一个上下文管理机制

    django的wsgi是web服务网关接口 wsgi是一个协议 实现这个协议的模块叫wsgiref,本质是创建socket服务,帮我们收发请求,我们就不用关注收发请求,而专注于业务处理. 我们写的程序是站在2个"巨人"的肩膀上,一个是wsgiref,;一个是web框架,一个写好socket,一个写好框架.
    jango和flask都依赖wsgi. tonardo不依赖wsgi.
    flask本身没有实现socket,flask也依赖wsgi, flask依赖一个第三方的wsgi模块werkzurg
    安装flask的时候会自动装上它依赖的werkzury

    一个最简单的flask程序:
    from flask import Flask

    app= Flask(__name__) #生成一个flask对象

    @app.route("/index") #创建路由
    def index():
    return "hello index"

    app.run() #app.run实际上就是启动socket


    response三剑客 return "xxx"
    return render_template('xx.html')
    return redirect('/xx')

    拿请求相关的数据,需要导入request
    from flask import request
    request.method # 请求方式
    request.form # 对应 request.post 存放FormData中的数据 前端表单类的数据都是formdata to_dict将formdata序列化成字典
    request.args # 对应request.get 获取URL中的数据 to_dict 序列化成字典
    request.url # 访问的完整路径
    request.path # 路由地址
    request.host # 主机地址
    request.values # 获取 FormData 和 URL中的数据 不要用to_dict可能会有坑,因为2个类型的数据的key有重复会覆盖
    request.json # 如果提交时请求头的Content-Type:是application/json,就将数据序列化放在request.json中字典操作
    request.data # 如果提交时请求头中的Content-Type无法被识别 放的是请求体中的原始数据 是bytes类型的原始数据
    request.cookies # 获取Cookie中的数据
    request.headers # 获取请求头
    request.files # 前端提交文件用request.files获取文件 序列化文件存储 save(路径) 将文件保存到本地

    给模板传值的2种方式:
    return render_template('login.html',error = '账号密码不正确')
    return render_template('login.html',**{'error' : '账号密码不正确'})

    session:
    django的session放在数据库中,flask的session放在加密的客户端, session的value是加密的.
    给session的加密的加盐 app.secret_key='dingyunfeng' #使用session就必须加盐,不加盐报错

    导入session: from flask import Flask,session
    session['username']=username #写入session
    user=session.get('username') #获取session

    昨天回顾:
    1.谈谈你对django和flask的认识。
    djaong是个大而全的框架, 内部提供了很多组件比如admin,auth,orm,form, modelform,分页缓存信号等方便的组件,只要在配置文件中修改就可以用. 而flask是一个轻量级的小而精的框架,是可扩展性很强的框架,flask常用于开发小型网站,但是开发大型网站也可以,因为它内部提供了很多很多第三方组件,flask和第三方组件结合起来也可以开发和djaong类似的集成了很多功能的框架,可定制性很强.

    2.目前你看到flask和django最大的不同点:request 和 session
    dj中session依附在reqeust中. flask中直接导入
    dj中request通过参数传递,flask直接导入


    3.昨天学的flask知识点

    -- 模板+静态文件,app= Flask(__name__,static_folder='static111') #在实例化flask对象的时候配置模板和静态文件目录

    -- 路由 用装饰器
    @app.route('/index',methods=["GET"])

    -- 请求相关
    request.form 类似dj中request.post
    request.args 类似dj中request.get
    request.method

    -- 响应
    "字符串"
    render
    redirect

    -- session
    session['username'] = 'alex' #设置session 用secret_key加密跟着response的cookie一起存到客户端,请求的时候带上cokie, flask收到cookie中的session通过secret_key反序列化.
    session.get('name') #取值 不要用[]取,防止keyError

    4. 路飞总共有几个项目
    - 管理后台
    - 导师后台
    - 主站--我们写的是主站 基于前后端分离来做的

    5. 路飞主站业务 #要能把如何实现都说出来
    -- 课程
    - 课程列表
    - 课程详细
    - 大纲、导师、推荐课程
    - 价格策略
    - 章节和课时
    - 常见问题
    -- 深科技
    - 文章列表
    - 文章详细
    - 收藏
    - 评论
    - 点赞
    -- 支付
    - 购物车(4)
    - 结算中心(3)
    - 立即支付(1)
    知识点:
    - redis 持久化方法1.aof 2.rdb 为什么要把数据放在redis中1.频繁操作/修改/删除 .2.提高速度
    - 支付宝
    - 消息推送
    - 构建数据结构
    - 优惠券+贝里+支付宝
    - 个人中心
    - 课程中心

    6. 播放视频:用CC视频 本质上视频是从cc来的
    - 加密
    - 非加密


    今日内容:
    flask基础中所有的基础有下面11个内容:
    1.配置文件.
    2.路由系统.
    3.视图 fbv cbv
    4.请求相关
    5.响应相关
    6.模板渲染
    7.session 以加密的形式放在客户端的cookie中
    8.flash闪现 闪一下就没有了 数据只要有1个人取就没了
    9.中间件
    10.蓝图blueprint 对flask程序做一个目录的划分
    11.特殊装饰器 类似django的中间件

    内容详细:
    知识点:
    - 给你一个路径字符串 “settings.Foo”,如何找到类并获取其中的大写的静态字段。 为了后面app.config.from_object("settings.DevelopmentConfig")做铺垫
    e.g有个文件settings.py 里面有:
    class Foo:
    DEBUG = True
    TEST = True

    test.py
    import importlib

    path = "settings.Foo"

    p,c = path.rsplit('.',maxsplit=1)
    m = importlib.import_module(p)
    cls = getattr(m,c) #反射找到类cls

    # 如果找到这个类? dir(类名)拿到类中所有的字典,
    for key in dir(cls): #dir()列出一个模块所定义的所有属性。这些属性是函数名、类名、变量名。
    if key.isupper():
    print(key,getattr(cls,key))
    1. 配置文件
    #flask的配置信息
    用app.config配置
    print('app.config')的结果为:
    <Config {'ENV': 'production', 'DEBUG': False, 'TESTING': False, 'PROPAGATE_EXCEPTIONS': None, 'PRESERVE_CONTEXT_ON_EXCEPTION': None, 'SECRET_KEY': None, 'PERMANENT_SESSION_LIFETIME': datetime.timedelta(31), 'USE_X_SENDFILE': False, 'SERVER_NAME': None, 'APPLICATION_ROOT': '/', 'SESSION_COOKIE_NAME': 'session', 'SESSION_COOKIE_DOMAIN': None, 'SESSION_COOKIE_PATH': None, 'SESSION_COOKIE_HTTPONLY': True, 'SESSION_COOKIE_SECURE': False, 'SESSION_COOKIE_SAMESITE': None, 'SESSION_REFRESH_EACH_REQUEST': True, 'MAX_CONTENT_LENGTH': None, 'SEND_FILE_MAX_AGE_DEFAULT': datetime.timedelta(0, 43200), 'TRAP_BAD_REQUEST_ERRORS': None, 'TRAP_HTTP_EXCEPTIONS': False, 'EXPLAIN_TEMPLATE_LOADING': False, 'PREFERRED_URL_SCHEME': 'http', 'JSON_AS_ASCII': True, 'JSON_SORT_KEYS': True, 'JSONIFY_PRETTYPRINT_REGULAR': False, 'JSONIFY_MIMETYPE': 'application/json', 'TEMPLATES_AUTO_RELOAD': None, 'MAX_COOKIE_SIZE': 4093}>

    #修改配置信息
    e.g 可以用 app.config['DEGBU']=True 来修改 如果修改的信息比较多,很多行看着麻烦,所以可以用app.config.from_object("settings.DevelopmentConfig")
    然后写一个settings.py,里面写class DevelopmentConfig,在class DevelopmentConfig里面写所有要配置的信息,
    e.g class DevelopmentConfig: #写开发环境的配置
    DEGUG=true

    class Config(object):
    DEBUG = False
    TESTING = False
    DATABASE_URI = 'sqlite://:memory:'

    class ProductionConfig(Config): #写生产环境的config
    DATABASE_URI = 'mysql://user@localhost/foo'

    class DevelopmentConfig(Config):
    DEBUG = True

    class TestingConfig(Config): # 写测试环境的config
    TESTING = True

    2. 路由系统 endpoint url_for
    - endpoint,反向生成URL类似dgngo路由中的name,#不写endpoint默认是函数名
    - url_for('endpoint') / url_for("index",nid=777)

    url_for对应django中的reverse
    endpoint对应django中的name 用于反向解析

    举例:
    @app.route('/index',methods=["GET","POST"],endpoint='indexxx')#不写endpoint默认是函数名
    def index():
    print('访问的路径是:',url_for('indexxx'))
    return '欢迎登录index'

    if __name__ == "__main__":
    app.run()


    - 动态路由:路由的参数传给函数的参数
    @app.route('/index/<int:nid>',methods=['GET','POST']) # 不写参数类型默认是string类型
    def index(nid):
    print(nid)
    return "Index"

    #有参数的路由反向解析的时候 url_for('index',nid=999) 那么解析出的路由是/index/999

    3. FBV


    4. 请求相关
    # 请求相关信息 所有请求的信息都能获取到
    # request.method
    # request.args
    # request.form
    # 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))

    5. 响应:
    响应体:#下面这4种只是返回响应体
    return “asdf”
    return jsonify({'k1':'v1'}) #返回json格式的数据 返回的contentype就是json
    return render_template('xxx.html')
    return redirect()

    定制响应头:#*****
    obj = make_response("aaa") # 用make_response封装一个响应对象,响应体是aaa
    obj.headers['xxx'] = '123' #设置响应头 xxx: 123456
    obj.set_cookie('islogin', 'yes') #设置cookie islogin yes
    return obj


    举例:学生管理


    版本一:没加认证的学生信息管理
    @app.route('/index')
    def index():
    if not session.get('user'):
    return redirect(url_for('login'))
    return render_template('index.html',stu_dic=STUDENT_DICT)

    版本二:加了认证的学生信息管理
    import functools
    def auth(func):
    @functools.wraps(func)
    def inner(*args,**kwargs):
    if not session.get('user'):
    return redirect(url_for('login'))
    ret = func(*args,**kwargs)
    return ret
    return inner

    @app.route('/index')
    @auth
    def index():
    return render_template('index.html',stu_dic=STUDENT_DICT)

    应用场景:比较少的函数中需要额外添加功能。

    完整版加了认证的学生信息查看:
    from flask import Flask, render_template, request, session, redirect, url_for, make_response
    import functools

    app = Flask(__name__, static_folder='static111')
    app.secret_key = 'dingyunfeng'

    @app.route('/login',methods=["GET", "POST"])
    def login():
    if request.method == "GET":
    return render_template("login.html")

    username = request.form.get('username')
    pwd = request.form.get('pwd')

    if username == 'alex' and pwd == '123':
    session['username'] = username # 登录成功 把用户名写入session
    return redirect(url_for('index'))

    return render_template('login.html', error='账号密码不正确')

    def auth(func):
    @functools.wraps(func) #用functools.warps()装饰,使装饰了的函数保留原来的函数名,
    # 否则所有装饰这个函数的函数名都是inner,
    #而endpoint没指定的时候默认是函数名,所有函数的endpoint都是inner会报错
    def inner(*args,**kwargs):
    if not session.get('username'): #如果没取到用户名表示没有登录,重定向到login页面
    return redirect(url_for('login'))
    ret = func(*args,**kwargs)
    return ret
    return inner

    STU_INFO = {
    1: {'name': 'alex', 'age': 18, 'hobby': 'women'},
    2: {'name': '丁云凤', 'age': 20, 'hobby': 'club'},
    3: {'name': 'max', 'age': 30, 'hobby': '唱歌'},
    4: {'name': '令狐冲', 'age': 40, 'hobby': '喝酒'}
    }
    @app.route('/index', methods=["GET", "POST"],endpoint='index')
    @auth
    def index(): #inex页面加上认证装饰器 先认证 通过认证再进入index
    return render_template('index.html', stu_info=STU_INFO)

    @app.route('/detail/<int:pid>')
    @auth
    def detail(pid):
    return render_template('detail.html', stu_info=STU_INFO[pid])

    @app.route('/delete/<int:pid>')
    @auth
    def delete(pid):
    del STU_INFO[pid]
    return redirect(url_for('index')) #删除后重定向到index页面,用反向路由重定向

    if __name__ == "__main__":
    app.run(debug=True)


    版本三:基于before_request的认证
    每个函数都要加认证装饰器 比较麻烦,加装饰器适用给某单个函数加功能, 如果要给大量函数加功能,用before_request
    before_request类似djanog中process_reqeust 在视图函数之前执行,如果before_request无返回值,就继续执行视图函数,有返回值就直接返回不执行视图函数

    @app.before_request
    def br():
    if request.path == '/login':
    return None #return None就表示继续执行视图函数 如果是login页面 要继续执行login

    if session.get('user'): #如果sesison中取到了user 表示认证通过 return None,继续执行视图函数
    return None

    return redirect('/login') #return 有返回值,就直接返回不执行视图函数


    6. 模板渲染
    - 基本数据类型:可以执行python的语法,如:dict.get() list['xx'] 或用句点符 dict.name

    - 传入函数
    - django会自动执行
    - flask不自动执行 要func()执行才会执行

    - 全局定义函数 @app.template_global()
    有些函数100个页面都要用 那么100个页面中传模板的时候都要带上这个函数,就可以将它定义成全局函数,所有页面直接引用
    @app.template_global()
    def sb(a1, a2): # 前端使用: {{sb(1,9)}}
    return a1 + a2

    @app.template_filter()
    def db(a1, a2, a3): # 前端使用 {{ 1|db(2,3) }} 可以用在if后面当条件e.g {%if 1|db(2,3) %}...
    return a1 + a2 + a3

    - 模板继承 和django中一样 extends/include/macro
    layout.html
    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
    <meta charset="UTF-8">
    <title>Title</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    </head>
    <body>
    <h1>模板</h1>
    {% block content %}{% endblock %}
    </body>
    </html>

    tpl.html中
    {% extends "layout.html"%}


    {% block content %}
    {{users.0}}

    {% endblock %}

    - include 包含一个小的html页面

    {% include "form.html" %}


    form.html
    <form>
    asdfasdf
    asdfasdf
    asdf
    asdf
    </form>
    - 宏 相当于执行一个函数 模板可以多次执行
    {% macro input1(name, type='text', value='') %} # macro相当于def, marco定义一个代码块 定义完不显示, 调用的时候显示
    <h1>宏</h1>
    <input type="{{ type }}" name="{{ name }}" value="{{ value }}">
    <input type="submit" value="提交">
    {% endmacro %}

    {{ input1('n1',type='password',111) }} #执行宏

    {{ input1('n2',222) }} #执行宏

    - 安全 模板渲染的时候默认加上了防xss攻击,
    如果要让文本用html形式渲染,
    - 前端: {{u|safe}}
    - 后端: MarkUp("asdf")


    7. session

    当请求一进来:flask读取cookie中session对应的值:eyJrMiI6NDU2LCJ1c2VyIjoib2xkYm95,将该值解密并反序列化成字典,放入内存以便视图函数使用
    当请求结束时,flask会读取内存中字典的值,进行序列化+加密,写入到用户cookie中。

    操作session的时候当做字典操作 session类似字典但不是字典
    操作是序列化再加密给客户端发过去例如:eyJrMiI6NDU2LCJ1c2VyIjoib2xkYm95. 获取后解密再反序列化使用.

    #和session有关的配置:在app.config中:
    'PERMANENT_SESSION_LIFETIME': timedelta(days=31), #session有效期
    'USE_X_SENDFILE': False,
    'SERVER_NAME': None,
    'APPLICATION_ROOT': '/',
    'SESSION_COOKIE_NAME': 'session', #在cookie中session显示的名字
    'SESSION_COOKIE_PATH': None,
    'SESSION_COOKIE_HTTPONLY': True,
    'SESSION_COOKIE_SECURE': False,
    'SESSION_COOKIE_SAMESITE': None,
    'SESSION_REFRESH_EACH_REQUEST': True, # session时效在每次访问的基础上开始算,也就是有效期从最后一次访问开始算,如果为false就从第一次设置session开始算. 一般都是true,就像淘宝在你最后一次请求开始算session的有效时间.-

    #e.g app.config["PERMANENT_SESSION_LIFETIME"]=timedelta(seconds=600) #设置session有效期为10分钟

    举例:

    @app.route('/ses')
    def ses():
    session['user'] = 'alex' #设置值 在浏览器中可以看见cookie中有
    print(session.get('user') #取值

    del session['k1'] #删session

    return "Session"




    8. flash闪现,在session中存数据,取一次就没有了,原理就是在session中存储数据读取后就pop将数据移除。放什么值都行,最后都会序列化
    # vs session中的数据只要不超时就一直在 无论取多少次
    设置数据flash('name','alex')
    取数据 get_flashed_messages(category_filter=['name'])


    from flask import Flask,flash,get_flashed_messages
    @app.route('/page1')
    def page1():

    flash('登录失败','error') # 将这个数据分类到error类中 取的时候get_flashed_messages(category_filter=['error']) 拿到所有error类下的数据,是个列表 e.g ['登录失败','没有这个用户']
    flash('没有这个用户','error')
    flash('登录成功','info') # 将这个数据分类到info类中
    flash('注册成功','info')

    return "Session"

    @app.route('/page2')
    def page2():
    print(get_flashed_messages(category_filter=['error']))
    return "Session"

    源码:
    def flash(message, category='message')
    #第二个参数是分类,可以数据进行分类, e.g flash('没有这个用户','error')给这个错误分类到error中
    ......

    取的时候get_flashed_messages(category_filter=['error']) 拿到所有error类下的数据,是个列表 e.g ['登录失败','没有这个用户']

    9. 中间件
    - 前提知识: call方法什么时候触发?
    - 有请求进来时,才执行__call__方法

    - 要实现: 在执行call方法之前,做一个操作,call方法执行之后做一个操作。
    方法1. 改源码,在源码的__call__方法中加代码.
    但是导致所有请求都会执行这个call方法

    方法2:类继承 重写call方法
    class Middleware(object):
    def __init__(self,old):
    self.old = old

    def __call__(self, *args, **kwargs):
    ret = self.old(*args, **kwargs)
    return ret

    if __name__ == '__main__':
    app.wsgi_app = Middleware(app.wsgi_app)
    app.run()


    10. 特殊装饰器 , #before_request/after_request就类似djaong的中间件

    1. before_request #来任何请求先执行before_request

    2. after_request #必须要有参数 必须要有返回值 类似djanog的process_response
    示例:
    from flask import Flask

    app = Flask(__name__)

    @app.before_request
    def b2():
    print('b2')

    @app.before_request
    def b1():
    print('b1')

    @app.after_request
    def a1(requset):
    print('a2')
    return requset

    @app.after_request
    def a1(requset):
    print('a1')
    return requset

    @app.route('/index')
    def index():
    print('index....')
    return 'helloworld'

    if __name__=='__main__':
    app.run(debug=True)

    #访问index结果: before_request谁先定义谁先执行 after_request谁后定义谁先执行.
    #总结 正序执行before_request--->执行视图函数--->倒序执行after_request
    b2
    b1
    index....
    a1
    a2

    有多个before_request,某个before_request有返回值,那么剩下的before_request不执行,倒序执行所有的after_request.
    vs 和django不一样 django的process_request有返回值的时候,从当前中间件的process_response开始倒序执行.(#djaong的1.10之前是和flask一样执行所有的respone, djaong的1.10后就从当前中间件的response开始倒序执行response)


    3. before_first_request # 只有第一次请求执行, 之后请求就不再执行

    from flask import Flask
    app = Flask(__name__)

    @app.before_first_request
    def x1():
    print('123123')


    @app.route('/index')
    def index():
    print('index')
    return "Index"


    @app.route('/order')
    def order():
    print('order')
    return "order"


    if __name__ == '__main__':

    app.run()


    4. template_global 给模板用的

    5. template_filter 给模板用的

    6. errorhandler # 自定制报错页面

    @app.errorhandler(404)
    def not_found(err_msg): #必须要有参数 这个参数用来接收真实404错误的报错信息
    print(err_msg)
    return "404错误 您要的页面没找到"

    总结:
    - 配置文件 # app.config.from_object("settings.DevelopmentConfig") 原理是字符串形式导入模块,反射找到里面内容,只有大写才能找到,因为源码中判断了isupper
    - 路由 route #url_for/ methods/ endpoint #记住加装饰器加载route下面,且写wraps装饰器为了避免endpoint都重名为inner,在写装饰器的inner的时候要@functools.wrapper
    - 视图:FBV
    - 请求相关数据 request和djaong不一样, 不是参数传入而是直接导入的
    - 响应
    - 响应体 return 'xx'/render_template /redirect
    - 自定制响应头
    obj = make_response("adfasdf")
    obj.headers['x'] = asdfasdf
    return obj
    - 模板
    template_global
    template_filter

    - session
    session内容会被序列化并加密存在客户端的cookie中
    原理是请求一进来就当请求一进来:flask读取cookie中session对应的值解密并反序列化成字典,放入内存以便视图函数使用
    当请求结束时,flask会读取内存中字典的值,进行序列化+加密,写入到用户cookie中。
    默认超时时间是31天
    - flash
    数据取一次就没有了
    原理是在session取数据后将数据pop

    - 中间件
    flask请求入口是__call__方法

    - 特殊装饰器
    before_request
    after_response
    before_first_request
    template_global
    template_filter
    errhander


    #=======================

    s9day116

    内容回顾:
    1. django和flask区别?
    部分回答:
    不同点 最大的不同点是 django中request和session通过参数传递 flask中通过上下文管理
    相同点 都是基于wsgi协议 (提供的socket服务)
    2.什么是wsgi?
    是web服务网关接口,wsgi是一个协议,实现该协议的模块有:
    - wsgiref模块 #djanog中用的
    - werkzeug模块 #flask中用的
    实现wsgi协议的模块本质上就是socket server用于接收用户请求并处理,只专注于处理请求,对业务的处理交给框架,
    一般的web框架都是基于wsgi实现,这样实现关注点分离。web框架只专注于处理业务.目前的web框架除了tonardo其他都是基于wsgi来做.

    wsgiref示例:
    from wsgiref.simple_server import make_server

    def run_server(environ, start_response):
    start_response('200 OK', [('Content-Type', 'text/html')])
    return [bytes('<h1>Hello, web!</h1>', encoding='utf-8'), ]


    if __name__ == '__main__':
    httpd = make_server('127.0.0.1', 8000, run_server) #表示请求进来会对第三个参数加括号,run_server()就执行run_server
    httpd.serve_forever()

    werkzeug示例:
    from werkzeug.wrappers import Response
    from werkzeug.serving import run_simple

    def run_server(environ, start_response):
    response = Response('hello')
    return response(environ, start_response)

    if __name__ == '__main__':
    run_simple('127.0.0.1', 8000, run_server)

    Flask源码入口:
    from werkzeug.wrappers import Response
    from werkzeug.serving import run_simple

    class Flask(object):
    def __call__(self,environ, start_response):
    response = Response('hello')
    return response(environ, start_response)

    def run(self):
    run_simple('127.0.0.1', 8000, self)#请求一进来,对第三个参数加括号,self()执行__call__方法

    app = Flask()

    if __name__ == '__main__':
    app.run()

    3. Flask提供功能
    - 1.配置文件
    - 所有配置都在app.config中
    - app.config["DEBUG"] = True
    - app.config.from_object("类的路径") #使用指定配置文件
    - 使用到了importlib、getattr,还有哪些功能是这样实现的?: django中间件和rest framework的全局配置

    - 2.session
    - 使用必须加盐app.secret_key
    - 序列化加密后放在浏览器的cookie中。
    - 流程:
    - 请求到来
    - 视图函数
    - 请求结束
    - 配置文件
    - 3.flash闪现
    - 基于session实现
    - 4.路由
    - 通过带参数的装饰器来实现
    - 自定义装饰器放下面
    - 参数
    - url_for
    - 5.视图
    - FBV
    - 6.请求和响应
    - 请求:request
    - 响应: 4种
    - 7.模板
    - ...
    - 8.特殊装饰器
    - before_first_request
    - before_request
    - after_request
    - template_global()
    - template_filter()
    - errorhandler(404)
    - 中间件

    今日内容:
    1. 路由+视图
    2. session实现原理(源码)
    3. 蓝图
    4. threading.local
    5. 上下文管理(第一次)

    内容详细:
    1. 路由+视图

    #route的源码:
    def route(self, rule, **options): #rule是xxx
    def decorator(f): # f是index
    endpoint = options.pop('endpoint', None)
    self.add_url_rule(rule, endpoint, f, **options) #当@app.route('/xxx') def index():的时候,最终执行的是app.add_url_rule(xxx, None,index. **options) 路由系统的本质就是执行了add_url_rule
    return f
    return decorator

    #通过源码可以看出路由的本质就是执行了add_url_rule,所以@app.route('/xxx') def index()也可以不加app.route装饰器写成app.add_url_rule('/xxx',None,index)
    所以routers=[('/xxx',index),]
    for item in routers:app.add_url_rule(item[0],None,item[1]) 也可以实现路由功能
    =====================================================
    1. 路由设置的两种方式:
    方式1:
    @app.route('/xxx')
    def index():
    return "123"

    方式2:
    def index():
    return "123"
    app.add_url_rule("/xxx",None,index)

    注意事项:
    - 不用让endpoint重名
    - 如果重名函数也一定要相同。

    2. app.route的参数
    rule, URL规则
    view_func, 视图函数名称
    endpoint=None, 名称,用于反向生成URL,即: url_for('名称')
    methods=None, 允许的请求方式,如:["GET","POST"] 不写默认为get
    strict_slashes=None, 对URL最后的 / 符号是否严格要求,
    redirect_to=None, 重定向到指定地址 #例如开发了新系统地址不一样了,用户还用旧地址,我们就可以重定向到新地址
    defaults=None, 默认值,当URL中无参数,函数需要参数时,使用defaults={'k':'v'}为函数提供参数
    subdomain=None, 子域名访问 e.g mall.authhome.com 或 sell.authhome.com
    e.g
    有 app.config['SERVER_NAME'] = 'oldboy.com'
    @app.route('/',subdomain='admin') #那么当访问 admin/oldboy.com的时候执行这个函数
    def xxx()....

    3. CBV
    import functools
    from flask import Flask,views
    app = Flask(__name__)

    def wrapper(func):
    @functools.wraps(func)
    def inner(*args,**kwargs):
    return func(*args,**kwargs)
    return inner

    #cbv 的url和视图对应关系不能用装饰器 只能用add_url_rule
    #和django一样,请求进来,as_view()中中执行view, view中return self.dispathch_request(*args,**kwargs)然后反射执行get/post
    #flask中cbv不多,一般都用fbv
    class UserView(views.MethodView):
    methods = ['GET'] #只允许GET请求
    decorators = [wrapper,] #给cbv中所有函数加上装饰器wrapper,也可以单独给每个函数加装饰器@wrapper

    def get(self,*args,**kwargs):
    return 'GET...'

    def post(self,*args,**kwargs):
    return 'POST...'

    app.add_url_rule('/user',None,UserView.as_view('uuuu'))

    if __name__ == '__main__':
    app.run()


    4. 路由中自定义正则 默认不支持自定义正则,我们可以让他支持
    from flask import Flask,url_for

    app = Flask(__name__)

    # 步骤一:定制类 继承BaseConverter
    from werkzeug.routing import BaseConverter
    class RegexConverter(BaseConverter):
    """
    自定义URL匹配正则表达式
    """

    def __init__(self, map, regex):
    super(RegexConverter, self).__init__(map)
    self.regex = regex

    def to_python(self, value): #to_pthon方法将url字符串变成int
    """
    路由匹配时,匹配成功后传递给视图函数中参数的值
    :param value:
    :return:
    """
    return int(value) #将url的字符串变成int

    def to_url(self, value): #反向生成URL时触发to_url
    """
    使用url_for反向生成URL时,传递的参数经过该方法处理,返回的值用于生成URL中的参数
    :param value:
    :return:
    """
    val = super(RegexConverter, self).to_url(value)
    return val

    # 步骤二:将自定制类添加到转换器converters
    app.url_map.converters['reg'] = RegexConverter #reg就代指RegexConverter

    """
    1. 用户发送请求
    2. init的self.regex = regex flask内部进行正则匹配
    3. 匹配成功后调用当前转换器的to_python(正则匹配的结果)方法,to_python()的返回值给视图函数的参数index(nid)
    """

    # 步骤三:使用自定义正则
    @app.route('/index/<reg("d+"):nid>') #reg就代指RegexConverter 类后加括号就是实例化执行构造方法init,
    def index(nid):
    print(nid,type(nid))

    print(url_for('index',nid=123))
    return "index"

    if __name__ == '__main__':
    app.run()

  • 相关阅读:
    c getline
    vim tips
    viksoe.dk UI: Become windowless
    用ls如何实现文件按时间排序查看,谢谢! AIX ChinaUnix.net
    垂直切分大小 : vertical res 30
    commandlinefu.com
    cmake 学习笔记(二) 1+1=2 博客频道 CSDN.NET
    implement split with c++
    分享:spdylay 0.3.8 发布,SDPY 的 C 语言实现
    培乐园《搜索相关性1》—在线播放—优酷网,视频高清在线观看
  • 原文地址:https://www.cnblogs.com/dingyunfeng/p/12866546.html
Copyright © 2020-2023  润新知