post请求在模板中要注意几点:html
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:global
1. g对象是专门用来保存用户的数据的。
2. g对象在一次请求中的全部的代码的地方,都是可使用的。web
使用步骤:
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中的函数flask
#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()
测试:
如今在浏览器里面,访问两次服务器,效果以下:浏览器
4、钩子函数
在程序正常运行的时候,程序按照A函数—->B函数的顺序依次运行;钩子函数能够插入到A函数到B函数运行中间从而,程序运行顺序变成了A—->钩子函数—->B函数。服务器
Flask项目中有两个上下文,一个是应用上下文(app),另一个是请求上下文(request)。请求上下文request和应用上下文current_app都是一个全局变量。全部请求都共享的。Flask有特殊的机制能够保证每次请求的数据都是隔离的,即A请求所产生的数据不会影响到B请求。因此能够直接导入request对象,也不会被一些脏数据影响了,而且不须要在每一个函数中使用request的时候传入request对象。这两个上下文具体的实现方式和原理能够不必详细了解。只要了解这两个上下文的四个属性就能够了:session
request:请求上下文上的对象。这个对象通常用来保存一些请求的变量。好比method、args、form等。
session:请求上下文上的对象。这个对象通常用来保存一些会话信息。
current_app:返回当前的app。
g:应用上下文上的对象。处理请求时用做临时存储的对象。
经常使用的钩子函数
before_first_request:处理第一次请求以前执行。
例如如下代码:app
@app.before_first_request def first_request(): print 'first time request'
例如如下代码:函数
@app.before_request def before_request(): if not hasattr(g,'user'): setattr(g,'user','xxxx')
@app.teardown_appcontext def teardown(exc=None): if exc is None: db.session.commit() else: db.session.rollback() db.session.remove()
@app.template_filter def upper_filter(s): return s.upper()
例如:post
@app.context_processor def my_context_processor(): return {'current_user':'xxx'}
例如:
@app.errorhandler(404) def page_not_found(error): return 'This page does not exist',404
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 的话,那么就须要手动构建一个请求,这无疑是不合理的。
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