Flask模板--环境管理

1. 上下文简介

  • 上下文理解
  • 常驻内存中的全局变量
  • 程序运行状态与相关资源的合集
  • 操作系统调度/进程切换时需要保存的值
  • 参考文档

https://dormousehole.readthedocs.io/en/latest/templating.html#id6

  • Flask上下文源码
# globals.py
# -*- coding: utf-8 -*-
"""
    flask.globals
    ~~~~~~~~~~~~~

    Defines all the global objects that are proxies to the current
    active context.

    :copyright: 2010 Pallets
    :license: BSD-3-Clause
"""
from functools import partial

from werkzeug.local import LocalProxy
from werkzeug.local import LocalStack


_request_ctx_err_msg = """\
Working outside of request context.

This typically means that you attempted to use functionality that needed
an active HTTP request.  Consult the documentation on testing for
information about how to avoid this problem.\
"""
_app_ctx_err_msg = """\
Working outside of application context.

This typically means that you attempted to use functionality that needed
to interface with the current application object in some way. To solve
this, set up an application context with app.app_context().  See the
documentation for more information.\
"""


def _lookup_req_object(name):
    top = _request_ctx_stack.top
    if top is None:
        raise RuntimeError(_request_ctx_err_msg)
    return getattr(top, name)


def _lookup_app_object(name):
    top = _app_ctx_stack.top
    if top is None:
        raise RuntimeError(_app_ctx_err_msg)
    return getattr(top, name)


def _find_app():
    top = _app_ctx_stack.top
    if top is None:
        raise RuntimeError(_app_ctx_err_msg)
    return top.app


# context locals
_request_ctx_stack = LocalStack()
_app_ctx_stack = LocalStack()
current_app = LocalProxy(_find_app)
request = LocalProxy(partial(_lookup_req_object, "request"))
session = LocalProxy(partial(_lookup_req_object, "session"))
g = LocalProxy(partial(_lookup_app_object, "g"))

  • 参考文档

https://blog.csdn.net/yournevermore/article/details/88802371

2. 标准环境

2.1 应用上下文变量
  • 应用上下文:应用内都可访问
  • current_app
  • 生命周期:当前程序实例,多个程序会有多个current_app,重运行后不再是新的实例
  • g
  • 生命周期:一次请求周期,下次请求不再是当前g,不可以跨请求
2.2 请求上下文变量
  • 请求上下文:请求内可访问的内容
  • request
  • 生命周期:一次请求周期,下次请求不再是当前request,不可以跨请求
  • 不同的用户会会创建不同的request,
  • session
  • 生命周期:会话级,只要当前session未过期,可以跨请求
2.3 参考博客

https://segmentfault.com/a/1190000017814222
https://blog.csdn.net/m0_37323771/article/details/80645100

2.4 其他缺省全局变量
  • 缺省情况下,gsessionrequest全局变量可以在 Jinja2 模板中使用,除此之外,还有configurl_for()
  • config : 当前配置对象( flask.config ),也可以使用config.py配置文件
  • url_for()函数
2.5 案例Code
# demo.py

from flask import Flask,session, render_template, request, g
import os
from datetime import timedelta

app = Flask(__name__)


app.config['SECRET_KEY'] = os.urandom(24)
app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(days=7)


    
@app.route('/<username>')
def hello(username):
    session['username'] = username
    g.id = request.args.get("id")
    return render_template('session.html')


if __name__ == '__main__':
    app.run(debug=True)
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=>, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div>
        <p>{{ session }}</p>
        <p>{{ session.username | default("游客") }}</p>
        <p>{{ request }}</p>
        <p>{{ request.args["id"] | default("id") }}</p>
        <p>{{ g }}</p>
        <p>{{ g.id }}</p>
        <p>{{ g['id']| default('你好') }}</p>
    </div>
</body>
</html>

访问: http://127.0.0.1:5000/username?id=123

在这里插入图片描述

3. 环境处理器

  • @app.context_processor
  • 环境处理器,也叫上下文处理器,在模板被渲染前运行,作用是把新的变量自动引入模板环境中
  • 被改装饰器修饰的钩子函数返回一个字典,字典中的key会被模板中当成变量来渲染
  • 返回的字典不仅可以包含变量,也可以包含方法,切方法可以在模板中调用
@app.route('/')
def demo():
    return render_template('demo.html')


# 环境处理器
@app.context_processor
def my_context_processor():
    def add(n):
        return n + n
    return dict(username='zhangsan', func_add=add)

<body>
    <p>{{ username }}</p>     # zhangsan
    <p>{{ func_add(4) }}</p>  # 8
</body>
  • before_request:

装饰器/钩子函数
在请求/视图函数之前执行的

4. 全局函数

4.1 内置全局函数
  • dict()函数,方便生成字典型变量
{% set user=dict(name='zhangsan', age=18) %}
{{  user }}

# {'name': 'zhangsan', 'age': 18}
  • joiner()函数,分隔符函数
{% set sep = joiner(' | ') %}
{% for item in range(1,10) %}
   {{ sep() }}<span>{{ item }}</span>
{% endfor %}

# 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
  • cycler()函数
{% set cycle = cycler('odd', 'even') %}
<ul>
    {% for num in range(10,20,2) %}
    <li>Num is "{{ num }}", next line is "{{ cycle.current }}" line.</li>
    {% endfor %}
</ul>
>
Num is "10", next line is "odd" line.
Num is "12", next line is "odd" line.
Num is "14", next line is "odd" line.
Num is "16", next line is "odd" line.
Num is "18", next line is "odd" line.
4.2 自定义全局函数
  • 方式一:@app.template_global('name')
@app.template_global('func1')
def my_add(a, b):
    return a + b
<p>{{ func1(2, 3) | default('没有调用函数')}}</p>
  • 方式二:app.add_template_global(func, 'name')

def my_add(a, b):
    return a + b

app.add_template_global(my_add, 'func1')

5. 钩子函数

  • 使用场景
  • 在请求开始时,建立数据库连接;
  • 在请求开始时,根据需求进行权限校验;
  • 在请求结束时,指定数据的交互格式;
  • 常用钩子函数
  • before_first_request:在处理第一个请求前执行
  • before_request:请求已到达Flask,但还没有进入到具体的视图函数之前调用,一般用来处理后面需要用到的数据
  • after_request:如果没有抛出错误,在每次请求后可以修改视图函数的响应,必须要有return,且视图函数执行失败不会再执行。
  • teardown_request:在每次请求后执行
  • teardown_appcontext:异常处理。不管是否有异常,注册的函数 都会在每次请求之后执行。
  • template_filter:自定义过滤器时使用
  • context_processor:见上文
  • errorhandler :异常响应吗处理
  • g与钩子函数操作数据库

def connect_db():
    conn = pymysql.connect(**{
        'host':'ip',
        'user':'root',
        'password':'123456',
        'port': 3306 ,
        'database':'db01', #指定你的数据库名
        })
    return conn.cursor()


@app.before_request
def do_db():
    if 'db' not in g: 
        g.db = connect_db()
    

@app.teardown_request
def teardown_db(exception):
    db = g.pop('db', None)
    if db is not None:
        print('关闭游标')
        db.close()

@app.route('/')
def index():
    sql = 'select * from t_book ;'
    g.db.execute(sql)
    r = g.db.fetchall()
    if len(r) !=0:
        return '数据表有数据'
    return '数据表为空'
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值