Flask知识点整理(二)

reponse

reponse:响应对象,用来返回数据给客户端的
返回的形式有两种:

一. 直接返回
    1. 直接返回,响应体
        return 响应体

    2. 直接返回,响应体 + 状态码
        return 响应体,状态码

    3. 直接返回,响应体 + 状态码 + 响应头
        return 响应体,状态码,响应头


二.手动封装response对象返回
    resp = make_response(响应体)
    resp.status = 状态
    resp.headers[key] = value

from flask import Flask,make_response

app = Flask(__name__)


@app.route('/')
def hello_world():

    # 1. 直接返回,响应体
    # return "helloworld"

    # 2. 直接返回,响应体 + 状态码
    # return "helloworld",666
    # return "helloworld","666 BIGERROR"

    # 3. 直接返回,响应体 + 状态码 + 响应头
    # return "helloworld",888,{"Content-Type":"application/json","name":"banzhang"}

    # 二.手动封装response对象返回
    resp = make_response("helloworld")
    resp.status = "666"
    resp.headers["Content-Type"] = "application/json"

    return resp

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

请求钩子

flask中提供了四种常见的请求钩子,作用: 在访问正常的视图函数的时候,会顺带执行钩子所装饰的方法:

  • before_first_request
    • 在处理第一个请求前执行
    • ==* 第一次请求的时候执行,可以用来做初始化操作,比如:数据库表的创建,数据连接==
  • before_request
    • 在每次请求前执行
    • 如果在某修饰的函数中返回了一个响应,视图函数将不再被调用
    • ==*每次请求前执行, 可以用来对请求参数校验,统计工作==
  • after_request
    • 如果没有抛出错误,在每次请求后执行
    • 接受一个参数:视图函数作出的响应
    • 在此函数中可以对响应值在返回之前做最后一步修改处理
    • 需要将参数中的响应在此参数中进行返回
    • ==*每次请求后执行,适合对返回的数据类型做统一处理==
  • teardown_request:
    • 在每次请求后执行
    • 接受一个参数:错误信息,如果有相关错误抛出
    • ==*每次请求销毁后执行, 用来记录服务器内部异常的,将e可以写到文件中==

from flask import Flask,request

app = Flask(__name__)

#第一次请求的时候执行,可以用来做初始化操作,比如:数据库表的创建,数据连接
@app.before_first_request
def before_first_request():
    print("before_first_request")

#每次请求前执行, 可以用来对请求参数校验,统计工作
@app.before_request
def before_request():

    #获取请求参数
    token = request.args.get("token")

    #假设校验参数, 进行解密,如果是123, 证明是非法请求
    if token == "123":
        return "你是坏蛋,非法请求!!!"

    print("before_request")

#每次请求后执行,适合对返回的数据类型做统一处理
@app.after_request
def after_request(resp):
    print("after_request")

    resp.headers["Content-Type"] = "application/json"
    return resp

#每次请求销毁后执行, 用来记录服务器内部异常的,将e可以写到文件中
@app.teardown_request
def teardown_request(e):
    print(e)
    print("teardown_request")

@app.route('/')
def hello_world():

    print("helloworld")

    return "helloworld"

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

cookie: 用来记录浏览器和服务器之间的交互信息,由服务器设置,存储在浏览器设置方式:
response.set_cookie(key,value,max_age)

max_age: 有效时间,单位秒, 如果不设置默认就是一次浏览器会话结束.

获取方式:

request.cookies.get(key)

from flask import Flask,make_response,request

app = Flask(__name__)

@app.route('/set_cookie')
def set_cookie():

    #获取响应体对象
    response = make_response("设置cookie")

    #设置cookie
    response.set_cookie("name","banzhang")
    response.set_cookie("age","29",10) #设置有效期为10秒

    #返回
    return response

@app.route('/get_cookie')
def get_cookie():

    #1.从request中获取cookie
    name = request.cookies.get("name")
    age = request.cookies.get("age")

    #2.返回
    return "name is %s, age is %s"%(name,age)


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

Session

session: 也是用来记录信息,记录敏感信息,比如:银行卡号,手机号,密码等信息,当前浏览器访问的时候,由服务器设置,存储在服务器.

设置:
session[key] = value

获取
session.get(key)

注意点:

  1. session在存储的时候会,先将session空间的地址加密(钥匙sessionID),存储到cookie中
  2. 由于sessionID的生成是加密的,所以需要设置SECRET_KEY
from flask import Flask,session

app = Flask(__name__)

#设置SECRET_KEY
app.config["SECRET_KEY"] = "jfkdjfkdjfkdj"


#设置session空间内容
@app.route('/set_session/<mobile>')
def set_session(mobile):

    #设置内容到session
    session["mobile"] = mobile

    return "设置session内容"


@app.route('/get_session')
def get_session():

    #获取session内容
    mobile = session.get("mobile")

    #返回
    return "mobile is %s"%(mobile)

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

上下文

flask中提供了两种类型的上下文对象

请求上下文:

request: 每次请求,封装对象为request

session: 第一次请求的时候,在服务器内部,开辟空间存储客户端的敏感信息(今后会指定session存储位置)

应用上下文:

current_app: 相当于app的代理对象,可以获取到app身上所有的相关配置信息,主要用在模块化开发中.

g: 主要用在装饰器里面,在一次完整的请求中都有效.

from flask import Flask,current_app,g

app = Flask(__name__)


@app.before_request
def test():

    g.name = "fubanzhang"


@app.route('/')
def hello_world():

print(current_app.url_map)
    print(g.name)

    return "helloworld"

if __name__ == '__main__':

    print(app.url_map)

    app.run(debug=True)

Flask_script

flask_script: 因为flask框架没有提供额外的功能,所以如果要使用邮件发送,数据库操作,数据库迁移等功能就需要安装扩展包

作用: 动态的运行程序,指定端口和ip

操作步骤:

1. 安装flask_script,导入
    pip install flask_script

2. 使用Manager类,来管理app
    manager = Manager(app)

3.启动,命令的方式
    python xxx.py runserver -h IP地址 -p 端口
from flask import Flask
from flask_script import Manager

app = Flask(__name__)

class Config(object):
    DEBUG = True

app.config.from_object(Config)

# 使用Manager类,来管理app
manager = Manager(app)

@app.route('/')
def hello_world():

    return "helloworld"

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

Jinja2模板

如果在flask框架中想要渲染页面需要使用jinja2, 里面提供了render_template()方法来渲染模块
使用流程:
1. 导入render_template

2. 渲染页面,携带数据
return render_template('文件名',key=value)
注意点:文件名是存在templates中,是app创建的时候默认参数

3.在文件中,取出数据展示


模板文件语法:
1.取出变量的值
{{ 变量名 }}

2.分支语句if
{% if 条件A %}
    语句1
{% elif 条件B %}
    语句2
{%else%}
    语句3
{% endif %}

执行流程:
    1.判断条件A, 如果为true走语句1
    2.如果条件A,为False,判断条件B,如果为true
    3...同理


3.循环语句for
{% for 变量 in 容器%}

{%endfor%}

4.注释
{# 注释内容 #}

python文件

from flask import Flask,render_template

app = Flask(__name__)

@app.route('/')
def hello_world():

    #定义数据
    num = 10
    my_str = "hello"
    my_tuple = (1,2,3,4,5)
    my_list = [6,7,8,9,10]
    my_dict= {
        "name":"班长",
        "age":29
    }

    #将数据渲染到模块中
    return render_template('file01template.html',num=num,str=my_str,tuple=my_tuple,list=my_list,dict=my_dict)

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

html文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>模板文件</title>
</head>
<body>

    <!--<h1>welcome to template</h1>-->

    <h1>1.取出变量中内容</h1>
    <h2>整数: {{ num + 10 }}</h2>
    <h2>字符串: {{ str }}</h2>
    <h2>元祖: {{ tuple }}, 分开取出内容,{{ tuple[0] }}, {{ tuple.1 }}</h2>
    <h2>列表: {{ list }}, 分开取出内容,{{ list.0 }}, {{ list[1] }}</h2>
    <h2>字典: {{ dict }}, 分开取出内容,{{ dict.name }},{{ dict['age'] }}</h2>


    <h1>2.遍历元祖中所有偶数</h1>
    {% for item in tuple %}
        {% if item %2 == 0 %}
            {{ item }}
        {% endif %}

    {% endfor %}

    <h1>3.取出列表中所有奇数</h1>
    {% for item in list %}
        {% if item %2 != 0 %}
            {{ item }}
        {% endif %}
    {% endfor %}

    <h1>4.遍历字典内容</h1>
    {# 遍历字典得到的是key, 通过key取出内容 #}
    {% for key in dict %}
        <li>{{ key }} = {{ dict[key] }}</li>
    {% endfor %}



</body>
</html>

模板过滤器

在模板中提供了一些自带的过滤器,作用是用来刷选某些需要的数据.
有两种方式:

    1. 字符串过滤器
        格式: {{ 字符串 | 字符串过滤器 }}

        字符串过滤器种类:
        lower: 字符串转小写
        upper: 字符串转大写
        ...

    2. 列表过滤器
        格式: {{ 列表 | 列表过滤器 }}
        列表过滤器:
        sort: 排序
        length: 列表长度
        first: 取出列表第1个元素

…..

python

from flask import Flask,render_template

app = Flask(__name__)

@app.route('/')
def hello_world():

    return render_template('file02filter.html')

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

html 文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

    <h1>1.字符串过滤器</h1>
    {#{{ 'hello' | reverse }}#}

    safe:禁用转义,(让标签生效)
    <p>{{ '<h1>hello</h1>' | safe}}</p>

    capitalize:把变量值的首字母转成大写,其余字母转小写
    <p>{{ 'hELLO' | capitalize }}</p>

    lower:把值转成小写,中文没有大小写
    <p>{{ 'HELLO哈哈' | lower }}</p>

    upper:把值转成大写
    <p>{{ 'hello' | upper }}</p>

    title:把值中的每个单词的首字母都转成大写
    <p>{{ 'hello world python' | title }}</p>

    reverse:字符串反转
    <p>{{ 'olleh' | reverse }}</p>

    format:格式化输出
    <p>{{ '%s is %d' | format('age',17) }}</p>

    striptags:渲染之前把值中所有的HTML标签都删掉, 让标签无效和safe相反
    <p>{{ '<h1>hello</h1>' | striptags }}</p>


    <h1>2.列表过滤器</h1>
    first:取第一个元素
    <p>{{ [1,2,3,4,5,6] | first }}</p> {# 1 #}

    last:取最后一个元素
    <p>{{ [1,2,3,4,5,6] | last }}</p> {# 6 #}

    length:获取列表长度
    <p>{{ [1,2,3,4,5,6] | length }}</p>{# 6 #}

    sum:列表求和
    <p>{{ [1,2,3,4,5,6] | sum }}</p>{# 21 #}

    sort:列表排序
    <p>{{ [6,2,3,1,5,4] | sort }}</p>{#  #}

</body>
</html>

自定义过滤器

为什么要自定义过滤器,因为系统提供的过滤器有可能满足不了需求
步骤:
方式一:
1.编写具有具体过滤功能的函数
2.将函数添加到,过滤器列表中
    app.add_template_filter(函数名,过滤器名称)

方式二:
在定义函数的时候,直接使用过滤器装饰器装饰
    @app.template_filter(过滤器名称)
from flask import Flask,render_template

app = Flask(__name__)


#过滤出列表中的所有偶数
def do_filter_oushu(list):

    # print(list)

    list2 = []
    for item in list:
        if item %2 == 0:
            list2.append(item)

    return list2

#将函数添加到,过滤器列表中
app.add_template_filter(do_filter_oushu,"my_oushu_filter")



# 在定义函数的时候,直接使用过滤器装饰器装饰
@app.template_filter("my_filter_jishuSum")
def do_filter_jishuSum(list):

    sum = 0

    for item in list:
        if item %2 != 0:
            sum += item

    return sum


@app.route('/')
def hello_world():

    return render_template('file03custom_filter.html')

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

对宏(macro)的理解:
    把它看作 Jinja2 中的一个函数,它会返回一个模板或者 HTML 字符串
    为了避免反复地编写同样的模板代码,出现代码冗余,可以把他们写成函数以进行重用
    需要在多处重复使用的模板代码片段可以写入单独的文件,再包含在所有模板中,以避免重复

定义宏:
{% macro 宏名(参数)%}

{% endmacro %}

调用:
1.当前文件定义的
{{ 宏名(参数)}}

2.其他文件文件定义
{% import '宏文件' as 别名 %}
{{ 别名.宏名(参数)}}

宏使用 使用本地和导入其他文件宏

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

    {# 定义宏 #}
    {% macro input(val) %}
        <input type="text" value="{{ val }}"><br>
        <input type="text" value="密码"><br>
    {% endmacro %}

    {# 调用宏 #}
    {{ input("用户名") }}
    {{ input("邮箱") }}
    {{ input("手机号") }}


    {# 使用其他文件宏 #}
    {% import 'file06otherMacro.html' as other_macro %}

    {{ other_macro.input2() }}

</body>
</html>

被导入html文件

{# 专门放一些共用代码 #}

{% macro input1(val) %}

    <input type="text" value="{{ val }}"><br>
    <input type="text" value="密码"><br>

{% endmacro %}

{%  macro input2() %}

    <h1>这是一个固定的表单</h1>
    <h1>这是一个固定的表单</h1>
    <h1>这是一个固定的表单</h1>

{% endmacro %}

继承 包含

模板的继承和包含:
模板继承:
    特点: 共性抽取,代码取用,子类可以扩展

模板包含:
    子文件中完全包含父类所有内容

语法:
继承: {% extends '文件名' %}

包含: {% include '文件名'%} 
包含: {% include '文件名' ignore missing%} 如果文件名不存在不报错 

在父文件中:
{% block 模块名字%}

{% endblock%}

父文件

{% block top %}
    <h1>史上最低价,狂甩了!!!</h1>
{% endblock %}

{% block content %}
    <h3>不要钱,不要钱,不要十块块钱,不要五块钱,只要一刻冰糖前,.....</h3>
{% endblock %}

{% block bottom %}
    <a href="http://www.taobao.com">点我有惊喜</a>
{% endblock %}

子文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

    {% extends 'file08fu.html' %}

    {# 重写父模板内容 #}
    {% block content %}
        {# 保留父类内容 #}
        {{ super() }}
        <h3>要钱,床前明月光......</h3>
    {% endblock %}

</body>
</html>

include 使用

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>包含</title>
</head>
<body>

    {# 如果文件名不存在不报错 #}
    {% include 'file07zi1.html' ignore missing %}

</body>
</html>

猜你喜欢

转载自blog.csdn.net/weixin_40420525/article/details/80880363