2018-12-17 初识Flask

一、flask介绍

  Flask和Django一样,也是一个基于MVC设计模式的Web框架

  Flask流行的主要原因:

    1. 有非常齐全的官方文档,上手非常方便
        
    2. 有非常好的拓展机制和第三方的拓展环境,工作中常见的软件都有对应的拓展,自己动手实现拓展也很容易
                
    3. 微型框架的形式给了开发者更大的选择空间

二、安装flask

    pip install flask

三、安装管理库

    pip install flask-script

四、导入管理库中的Manager,用Manager管理项目

将flask对象交给Manager管理如下
manage = Manager(app)
manage.run()

  用manage启动项目

    python hello.py runserver -h 0.0.0.0 -p 8080 -d

  参数说明:

    -h 指定主机地址
    -p 指定端口号
    -d 指定用debug方式启动 
    
    路由接收参数
    @app.route('/stu/<id>/')
    def stu(id):
        # 接收的参数是字符串
        return f'stu id: {id}'
    
    @app.route('/grade/<int:id>/')
    def grade(id):
        # 指定接收的参数是int类型
        return f'grade id: {id}'

    可以指定许多接收参数类型但常用的就是int和string
@app.route('/path/<path:url>/')
def get_path(url):
    # 接收url中path后面的全部路径
    return f'url: {url}'


@app.route('/get_uuid/')
def get_uuid():
    import uuid
    # 获取一个uuid,uuid是一个唯一的字符串
    return str(uuid.uuid4())


@app.route('/uuid/<uuid:u>/')
def my_uuid(u):
    # 指定接收的参数为uuid类型的值
    return f'uuid: {u}'

  python框架主要

    Django
    Flask
    Tronado  
    Sanic    性能最优但是一般不再线上使用
    Twisted  主要是针对底层协议

  将flask项目提炼成mvc的形式

  安装蓝图(就是模块化管理路由),相当于Django中的urls.py

    pip install flask-blueprint

  使用:

    from flask import Blueprint
    # 模块化管理路由 Blueprint
    # 第一步:生成蓝图对象
    blueprint = Blueprint('first', __name__)
    # 第二步:在管理文件中注册一个蓝图,也就是将应用绑定在应用上
    app.register_blueprint(blueprint=blueprint, url_prefix='/app')
    # url_prefix: url访问前缀127.0.0.1/app/
    前缀相当于Django中的namespace

  路由跳转

@blueprint.route('/redirect/')
def my_redirect():
    # 跳转到无参方法
    # redirect: 跳转
    # url_for:反向解析出地址
    # 'first.hello_world': 蓝图第一个 参数.跳转到的函数名
    return redirect(url_for('first.hello_world'))

@blueprint.route('/redirect_id/')
def stu_redirect():
    # 有参数的跳转
    return redirect(url_for('first.stu', id=3))

五、请求与相应

  1. 请求:

@blueprint.route('/req/', methods=['GET', 'POST', 'PUT', 'PATCH', 'DELETE'])
def req():
    # methods = ['GET', 'POST']指定能接收的请求类型
    if request.method == 'GET':
        # 获取get请求中的参数
        # request.agrs.get(key)
        # 获取get请求中多个相同key的参数的值,返回列表
        # request.args.getlist(key)
        return 'hello get'

    if request.method == 'POST':
        # 获取post请求中传递的参数
        # request.form.get(key)
        # 获取post请求中相同key的参数,返回列表
        # request.form.getlist(key)

  2. 响应:

    从flask中导入响应模块
    创建响应对象
    res = make_response(响应内容,状态码)
    设置cookie
    res.set_cookie(key, value, max_age, expires)
    key: 键
    value: 值
    max_age: 过期时间,秒为单位
    expires: 过期时间,datetime为单位
    删除cookie
    方式一: res.delete_cookie(key)
    方式二: res.set_cookie(key, value, max_age=0) 过期时间为0相当于删除

六、装饰器验证登录状态

  装饰器的三个特点:

    1. 外层函数内嵌内层函数
    2. 内层函数调用外层函数的参数
    3. 外层函数返回内层函数

  自定义一个登录简单的登录验证装饰器

from flask import session, redirect, url_for

from functools import wraps

def login_status(func):
    # 使用functools装饰该内嵌函数,用于维持被装饰函数的部分属性,如__name__/__doc__/__module__
    @wraps(func)
    def check_login(*args, **kwargs):
        # 获取登录后在session中设置的user_id,由于标识用户登录状态
        user_id = session.get('user_id')
        if user_id:
            # 有user_id说明登录,则继续执行被装饰函数
            return func(*args, **kwargs)
        else:
            # 如果没有user_id说明没有登录,则跳转道登录界面
            return redirect(url_for('first.hello_world'))

    return check_login

  functools库函数简介
  1. update_wrapper
  更新一个包裹(wrapper)函数,使其看起来更像被包裹(wrapped)的函数。

  可选的参数指定了被包裹函数的哪些属性直接赋值给包裹函数的对应属性,同时包裹函数的哪些属性要更新而不是直接接受被包裹函数的对应属性,参数assigned的默认值对应于模块级常量WRAPPER_ASSIGNMENTS(默认地将被包裹函数的 namemodule,和 doc 属性赋值给包裹函数),参数updated的默认值对应于模块级常量WRAPPER_UPDATES(默认更新wrapper函数的 dict 属性)。

  这个函数的主要用途是在一个装饰器中,原函数会被装饰(包裹),装饰器函数会返回一个wrapper函数,如果装饰器返回的这个wrapper函数没有被更新,那么它的一些元数据更多的是反映wrapper函数定义的特征,无法反映wrapped函数的特性。

  2. wraps
  这个函数可用作一个装饰器,简化调用update_wrapper的过程,调用这个函数等价于调用partial(update_wrapper, wrapped = wrapped, assigned = assigned,updated = updated)。

from functools import wraps

def my_decorator(f):
    @wraps(f)
    def wrapper(*args,**kwds):
        print "Calling decorated function"
        return f(*args,**kwds)
    return wrapper

@my_decorator
def example():
    """DocString"""
    print "Called example function"

example()
print example.__name__
print example.__doc__

  控制台输出,

    Calling decorated function
    Called example function
    example
    DocString

  可以看到,最终调用函数example时,是经过 @my_decorator装饰的,装饰器的作用是接受一个被包裹的函数作为参数,对其进行加工,返回一个包裹函数,代码使用 @functools.wraps装饰将要返回的包裹函数wrapper,使得它的 namemodule,和 doc 属性与被装饰函数example完全相同,这样虽然最终调用的是经过装饰的example函数,但是某些属性还是得到维护。

如果在 @my_decorator的定义中不使用 @function.wraps装饰包裹函数,那么最终example.name 将会变成'wrapper',而example.doc 也会丢失。

将 @wraps(f)注释掉,然后运行程序,控制台输出,

    Calling decorated function
    Called example function
    wrapper
    None

  所以在上面我们自定义的登录状态验证装饰器就需要用到functools库中的wraps来装饰内嵌函数,维持被装饰的函数的_name_、_module_、_doc_属性,如果不用wraps装饰当我们在视图函数中进行反向解析被装饰函数时,会报如下错误:

1.png

如:

@blueprint.route('/')
@login_status
def hello_world():

    return 'hello'

@blueprint.route('/login/', methods=['GET', 'POST'])
def login():

    if request.method == 'GET':

        return render_template('login.html')

    if request.method == 'POST':
        # 模拟登录
        username = request.form.get('username')
        password = request.form.get('password')
        if username == 'root' and password == '123123':
            # 设置session值
            session['user_id'] = 1
        return redirect(url_for('first.hello_world'))  # 如果没有用@wraps装饰装饰器的内嵌函数则者句话在做反向解析时就会抛出上面提到的异常

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容