Flask零基础到项目实战(七)请求方法、g对象和钩子函数

一、get方法

二、post方法

post请求在模板中要注意几点:

  • input标签中,要写name来标识这个value的key,方便后台获取。
  • 在写form表单的时候,要指定method='post',并且要指定action='/login/'
  • 示例代码:
        <form action="{{ url_for('login') }}" method="post">
<table>
<tbody>
<tr>
<td>用户名:</td>
<td><input type="text" placeholder="请输入用户名" name="username"></td>
</tr>
<tr>
<td>密码:</td>
<td><input type="text" placeholder="请输入密码" name="password"></td>
</tr>
<tr>
<td></td>
<td><input type="submit" value="登录"></td>
</tr>
</tbody>
</table>
</form>

三、g对象

g:global
1. g对象是专门用来保存用户的数据的。
2. g对象在一次请求中的所有的代码的地方,都是可以使用的。

使用步骤:
1.创建一个utils.py文件,用于测试除主文件以外的g对象的使用
utils.py

#encoding: utf-8

from flask import g

def login_log():
print u'当前登录用户是:%s' % g.username def login_ip():
print u'当前登录用户的IP是:%s' % g.ip

2.在主文件中调用utils.py中的函数

#encoding: utf-8

from flask import Flask,g,request,render_template
from utils import login_log,login_ip app = Flask(__name__) @app.route('/')
def hello_world():
return 'Hello World!' @app.route('/login/',methods=['GET', 'POST'])
def login():
if request.method == 'GET':
return render_template('login.html')
else:
username = request.form.get('username')
password = request.form.get('password')
g.username = username
g.ip = password
login_log()
login_ip()
return u'恭喜登录成功!' if __name__ == '__main__':
app.run()

测试:
 现在在浏览器里面,访问两次服务器,效果如下:

四、钩子函数
 在程序正常运行的时候,程序按照A函数—->B函数的顺序依次运行;钩子函数可以插入到A函数到B函数运行中间从而,程序运行顺序变成了A—->钩子函数—->B函数。

 Flask项目中有两个上下文,一个是应用上下文(app),另外一个是请求上下文(request)。请求上下文request和应用上下文current_app都是一个全局变量。所有请求都共享的。Flask有特殊的机制可以保证每次请求的数据都是隔离的,即A请求所产生的数据不会影响到B请求。所以可以直接导入request对象,也不会被一些脏数据影响了,并且不需要在每个函数中使用request的时候传入request对象。这两个上下文具体的实现方式和原理可以没必要详细了解。只要了解这两个上下文的四个属性就可以了:

request:请求上下文上的对象。这个对象一般用来保存一些请求的变量。比如method、args、form等。
session:请求上下文上的对象。这个对象一般用来保存一些会话信息。
current_app:返回当前的app。
g:应用上下文上的对象。处理请求时用作临时存储的对象。
常用的钩子函数
before_first_request:处理第一次请求之前执行。
例如以下代码:

@app.before_first_request
def first_request():
print 'first time request'

before_request:在每次请求之前执行。通常可以用这个装饰器来给视图函数增加一些变量。

例如以下代码:

@app.before_request
def before_request():
if not hasattr(g,'user'):
setattr(g,'user','xxxx')

teardown_appcontext:不管是否有异常,注册的函数都会在每次请求之后执行。

@app.teardown_appcontext
def teardown(exc=None):
if exc is None:
db.session.commit()
else:
db.session.rollback()
db.session.remove()

template_filter:在使用Jinja2模板的时候自定义过滤器。比如可以增加一个upper的过滤器(当然Jinja2已经存在这个过滤器,本示例只是为了演示作用):

@app.template_filter
def upper_filter(s):
return s.upper()

context_processor:上下文处理器。返回的字典中的键可以在模板上下文中使用。

例如:

@app.context_processor
def my_context_processor():
return {'current_user':'xxx'}

errorhandler:errorhandler接收状态码,可以自定义返回这种状态码的响应的处理方法。

例如:

@app.errorhandler(404)
def page_not_found(error):
return 'This page does not exist',404

额外的讲解: g

g 也是我们常用的几个全局变量之一。在最开始这个变量是挂载在 Request Context 下的。但是在 0.10 以后,g 就是挂载在 App Context 下的。可能有同学不太清楚为什么要这么做。

首先,说一下 g 用来干什么

官方在上下文这一张里有这一段说明

The application context is created and destroyed as necessary. It never moves between threads and it will not be shared between requests. As such it is the perfect place to store database connection information and other things. The internal stack object is called flask.appctx_stack. Extensions are free to store additional information on the topmost level, assuming they pick a sufficiently unique name and should put their information there, instead of on the flask.g object which is reserved for user code.

大意就是说,数据库配置和其余的重要配置信息,就挂载 App 对象上。但是如果是一些用户代码,比如你不想一层层函数传数据的话,然后有一些变量需要传递,那么可以挂在 g 上。

同时前面说了,Flask 并不仅仅可以当做一个 Web Framework 使用,同时也可以用于一些非 web 的场合下。在这种情况下,如果 g 是属于 Request Context 的话,那么我们要使用 g 的话,那么就需要手动构建一个请求,这无疑是不合理的。

g一般用来传递上下文的数据,flask里面有很多钩子函数,例如before_first_request之类的,g提供了一个方法将数据共享到正常的路由函数里去。举个例子,你可以在before_request里面做Http Basic Authentication验证,然后将验证过的用户数据存在g里面,这样在路由函数里就可以直接调用g里面的用户数据了,而不用再搞个全局变量。这样非常方便

Flask中有两种上下文,请求上下文和应用上下文。

请求上下文(request context)
request和session都属于请求上下文对象。

request:封装了HTTP请求的内容,针对的是http请求。举例:user = request.args.get('user'),获取的是get请求的参数。

session:用来记录请求会话中的信息,针对的是用户信息。举例:session['name'] = user.id,可以记录用户信息。还可以通过session.get('name')获取用户信息。

应用上下文(application context)
current_app和g都属于应用上下文对象。

current_app:表示当前运行程序文件的程序实例。

g:处理请求时,用于临时存储的对象,每次请求都会重设这个变量。比如:我们可以获取一些临时请求的用户信息。

当调用app = Flask(_name_)的时候,创建了程序应用对象app;
request 在每次http请求发生时,WSGI server调用Flask.call();然后在Flask内部创建的request对象;
app的生命周期大于request和g,一个app存活期间,可能发生多次http请求,所以就会有多个request和g。
最终传入视图函数,通过return、redirect或render_template生成response对象,返回给客户端。
区别: 请求上下文:保存了客户端和服务器交互的数据。 应用上下文:在flask程序运行过程中,保存的一些配置信息,比如程序文件名、数据库的连接、用户信息等。

上下文对象的作用域
在flask项目中某一个功能中会有多个视图,那么from flask import request,current_app,session,g,怎么保证某次请求的上下文不会被别的视图拿走呢?

从pycharm中进入globals.py:

_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'))

线程有个叫做ThreadLocal的类,也就是通常实现线程隔离的类。而werkzeug自己实现了它的线程隔离类:werkzeug.local.Local。LocalStack就是用Local实现的。

LocalStack是flask定义的线程隔离的栈存储对象,分别用来保存应用和请求上下文。
它是线程隔离的意思就是说,对于不同的线程,它们访问这两个对象看到的结果是不一样的、完全隔离的。这是根据pid的不同实现的,类似于门牌号。

而每个传给flask对象的请求,都是在不同的线程中处理,而且同一时刻每个线程只处理一个请求。所以对于每个请求来说,它们完全不用担心自己上下文中的数据被别的请求所修改。

而这个LocalProxy 的作用就是可以根据线程/协程返回对应当前协程/线程的对象,也就是说

线程 A 往 LocalProxy 中塞入 A

线程 B 往 LocalProxy 中塞入 B

无论在是什么地方,

线程 A 永远取到得是 A,线程 B 取到得永远是 B

Flask中current_app和g对象的更多相关文章

  1. python web开发-flask中response,cookies,session对象使用详解

    Response响应对象: 当一个web请求被服务器处理完后,会返回用户请求的响应,这时候就要用到响应对象,根据响应给用户的形式不同,响应对象有以下几种处理方式 如果返回的是一个合法的响应对象,它会从 ...

  2. flask中的request.form对象方法

    'add','clear','copy','deepcopy','fromkeys','get','gtlist','has_key','items','iteritems','iterkeys',' ...

  3. flask中current_app._get_current_object()与current_app有什么区别?

    https://segmentfault.com/q/1010000005865632/a-1020000005865704

  4. Flask中g对象,以及g,session,flash之间的区别

    一.g对象的使用 专门用来存储用户信息的g对象,g的全称的为global g对象在一次请求中的所有的代码的地方,都是可以使用的 g对象的使用: 设置:g.变量名= 变量值 获取:g.name 注意:g ...

  5. Python框架学习之Flask中的视图及路由

    在前面一讲中我们学习如何创建一个简单的Flask项目,并做了一些简单的分析.接下来在这一节中就主要来讲讲Flask中最核心的内容之一:Werkzeug工具箱.Werkzeug是一个遵循WSGI协议的P ...

  6. flask中的上下文_请求上下文和应用上下文

    前引 在了解flask上下文管理机制之前,先来一波必知必会的知识点. 面向对象双下方法 首先,先来聊一聊面向对象中的一些特殊的双下划线方法,比如__call__.__getattr__系列.__get ...

  7. Flask上下文管理、session原理和全局g对象

    一.一些python的知识 1.偏函数 def add(x, y, z): print(x + y + z) # 原本的写法:x,y,z可以传任意数字 add(1,2,3) # 如果我要实现一个功能, ...

  8. flask系列八之请求方法、g对象和钩子函数

    一.get方法 ,post方法 post请求在模板中要注意几点: (1)input标签中,要写name来标识这个value的key,方便后台获取. (2)在写form表单的时候,要指定method=' ...

  9. flask框架(七)——蓝图、请求上下文、g对象、信号、flask_session

    蓝图 作用:对程序进行目录结构划分 不使用蓝图情况下,自己分文件 目录结构: -templates -views -__init__.py -user.py -order.py -app.py app ...

随机推荐

  1. Image Processing and Analysis_8_Edge Detection:Statistical edge detection_ learning and evaluating edge cues——2003

    此主要讨论图像处理与分析.虽然计算机视觉部分的有些内容比如特 征提取等也可以归结到图像分析中来,但鉴于它们与计算机视觉的紧密联系,以 及它们的出处,没有把它们纳入到图像处理与分析中来.同样,这里面也有 ...

  2. Ubuntu安装cmake 3.9

    wget https://cmake.org/files/v3.9/cmake-3.9.2.tar.gz # 下载 cd cmake-3.9.2 ./configure sudo make & ...

  3. 用js刷剑指offer(跳台阶)

    题目描述 一只青蛙一次可以跳上1级台阶,也可以跳上2级.求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果). 牛客网链接 思路 这一题和斐波那契数列思路完全一样. 假如青蛙从第n个 ...

  4. Exams(二分

    题意:给你每天要考的科目,和每门科目需要复习多长时间,问最少需要几天才能完成所有的考试. 思路:二分答案,然后判断答案是否可行,这边需要进行贪心,即倒着往前推, 比如第i天,那么前面有i-1天是,可供 ...

  5. Java字节码方法表与属性表深度剖析

    方法表: 在上一次咱们已经分析到了字段信息了,如下: 紧接着就是方法相关的信息了: 而它展开之后的结构为: 所以往后数2个字节,看一下方法的总数: 3个方法,可咱们只定义了两个方法呀: 因为编译器会为 ...

  6. MySQl 进阶一 基本查询及练习

    知识点及练习 USE myemployees; #.查询表中的单个字段 SELECT last_name FROM employees; #.查询表中多个字段 #.查询全部 SELECT * FROM ...

  7. hibernate的详解

    一,环境的搭建 1)创建maven项目 2)导入依赖的jar包.pom.xml和创建实体类User <?xml version="1.0" encoding="UT ...

  8. 使用Struts2+Hibernate开发学生信息管理功能1

    第一章:Struts2与Hibernate整合 1.课程简介 2.界面原型演示 3.Struts2与Hibernate整合 4.创建实体类 5.生成实体映射文件 6.生成表结构 1.课程简介 Stru ...

  9. Java锁--Condition

    转载请注明出处:http://www.cnblogs.com/skywang12345/p/3496716.html Condition介绍 Condition的作用是对锁进行更精确的控制.Condi ...

  10. unity 拿到管线权限的解决方案

    自己建个cmd 传给postprocess layer camera event可以加在这个cmd上控制位置  base pass post process ui都共享这段cmd 在一开始记下back ...