Flask

 

 

 


app = Flask(__name__)框架解析

初始化APP

flask.py

class Flask(object):
 
'''
全局变量
'''
    request_class = Request
    response_class = Response
    static_path = '/static'
    secret_key = None
    session_cookie_name = 'session'
    jinja_options = dict(
        autoescape=True,
        extensions=['jinja2.ext.autoescape', 'jinja2.ext.with_']
    )

request_class变量是一个Request类,Request类继承自werkzeug的Request类。它调用了werkzeug的Request类的构造函数,RequestBase.__init__(self, environ)。然后又初始化了endpoint和view_args两个变量。

response_class变量是一个Response类。继承自werkzeug的Reponse类。且自己初始化了变量 default_mimetype=‘text/html’

static_path是静态文件路径,默认值为/static

secret_key默认值为None

  如果设置了secret_key,加密组件使用这个key签名cookies。当你要使用安全cookie,你要把这个key设置成复杂的随机值

 

session_cookie_name,session的名字为session

jinja_options选项初始化

初始化构造函数:

def __init__(self, package_name):
        self.debug = False   #debug变量为False
        self.package_name = package_name  #一般为__name__,如果以本模块运行,则为__main__;如果是被调用,则为app文件名。
        self.root_path = _get_package_path(self.package_name)  #获取app的绝对路径
        self.view_functions = {}  #视图函数
        self.error_handlers = {}  #错误处理
        self.before_request_funcs = []  #HTTP请求之前需要执行的函数
        self.after_request_funcs = []   #HTTP请求结束之后,需要执行的函数
        self.template_context_processors = [_default_template_ctx_processor]  #上下文模板变量:session、g、request
         
        self.url_map = Map()  #url集合<br>
        if self.static_path is not None:   #self.static_path默认值为'/static',所以默认会把它加入到url_map集合中。Map([<Rule '/static/<filename>' -> static>])
            self.url_map.add(Rule(self.static_path + '/<filename>',
                                  build_only=True, endpoint='static'))
            if pkg_resources is not None:
                target = (self.package_name, 'static')
            else:
                target = os.path.join(self.root_path, 'static')
            self.wsgi_app = SharedDataMiddleware(self.wsgi_app, {
                self.static_path: target
            })      
        self.jinja_env = Environment(loader=self.create_jinja_loader(),
                                     **self.jinja_options)
        self.jinja_env.globals.update(
            url_for=url_for,
            get_flashed_messages=get_flashed_messages
        )

初始化构造函数中,主要定义了一些变量(debug、包名、包路径、视图函数、上下文相关、路由、static路径、模板相关环境)

路由处理

定义路由装饰器

def route(self, rule, **options):   #route装饰器,装饰路由的同时,把路由添加进Map,添加视图函数,确保路由和视图函数映射起来
        def decorator(f):
            self.add_url_rule(rule, f.__name__, **options)  #Map([<Rule '/hello'(HEAD,GET) -> hello_world>])
            self.view_functions[f.__name__] = f          #view_functions = {'hello_world':hello_world}
            return f
        return decorator<br>
def add_url_rule(self, rule, endpoint, **options):
 
        options['endpoint'] = endpoint
        options.setdefault('methods', ('GET',))
        self.url_map.add(Rule(rule, **options))

完成url_map和view_functions的初始化,其中Rule是werkzeug提供的工具

app.run()

app启动过程如下:

flask.run()
    --> werkzeug.run_simple()
    -->  werkzeug.inner()
       --> werkzeug.serving.make_server()
         -->serve_forever()
           -->SocketServer.BaseServer.HTTPServer.serve_forever()  #While True:****

 

 

# 引入Flask类,Flask类实现了一个WSGI应用
from flask import Flask


# app是Flask的实例,它接收包或者模块的名字作为参数,但一般都是传递__name__
# 让flask.helpers.get_root_path函数通过传入这个名字确定程序的根目录,以便获得静态文件和模板文件的目录
app = Flask(__name__)


# 使用app.route装饰器会将URL和执行的视图函数的关系保存到app.url_map属性上
# 处理URL和视图函数的关系的程序就是路由,这里的视图函数就是hello_world
@app.route('/')
def hello_world():
    return 'Hello World!'


# 使用这个判断可以保证当其他文件引用这个文件的时候(例如“from hello import app”)不会执行这个判断内的代码,也就是不会执行app.run函数。
if __name__ == '__main__':

    # 执行app.run就可以启动服务了。默认Flask只监听虚拟机的本地127.0.0.1这个地址,端口为5000
    # 而我们对虚拟机做的端口转发端口是9000,所以需要制定host和port参数,0.0.0.0表示监听所有地址,这样就可以在本机访问了
    app.run(host='0.0.0.0', port=9000)


'''
    服务器启动后,会调用werkzeug.serving.run_simple进入轮询,默认使用单进程单线程的werkzeug.serving.BaseWSGIServer处理请求,
    实际上还是使用标准库BaseHTTPServer.HTTPServer,通过select.select做0.5秒的“while TRUE”的事件轮询。
    当我们访问“http://127.0.0.1:9000/”,通过app.url_map找到注册的“/”这个URL模式,就找到了对应的hello_world函数执行,返回“hello world!”,状态码为200。
    如果访问一个不存在的路径,如访问“http://127.0.0.1:9000/a”,Flask找不到对应的模式,就会向浏览器返回“Not Found”,状态码为404
'''

 

 

 

g对象

在flask中,有一个专门用来存储用户信息的g对象,g的全称的为global

g对象在一次请求中的所有的代码的地方,都是可以使用的.

g 作为 flask 程序全局的一个临时变量,充当者中间媒介的作用,我们可以通过它传递一些数据,g 保存的是当前请求的全局变量,不同的请求会有不同的全局变量,通过不同的thread id区别

g对象和session的区别

最大的区别

session对象是可以跨request的,只要session还未失效,不同的request的请求会获取到同一个session,

但是,g对象不需要管过期时间,请求一次就g对象就改变了一次,或者重新赋值了一次.

g对象的使用实例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="" method="post">
    <table>
        <tbody>
        <tr>
            <td>用户名:</td>
            <td><input type="text" name="username" placeholder="请输入用户名"></td>
        </tr>
        <tr>
            <td>密码:</td>
            <td><input type="password" name="password" placeholder="请输入密码"></td>
        </tr>
        <tr>
            <td></td>
            <td><input type="submit" value="登录"></td>
        </tr>
        </tbody>
    </table>
</form>
</body>
</html>
login.html
###########app.py############
from flask import Flask,g,render_template,request
from utils import login_log
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')
        if username == '111' and password == '222':
       # 使用g对象 g.username
= '111' login_log() return u'登录成功' else: return u'您的用户名或密码错误' if __name__ == '__main__': app.run()
###########utils.py##############
from flask import g
def login_log():
    print('当前登录用户是',g.username)

 

使用步骤: 

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

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

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

出处:https://www.cnblogs.com/skyflask/p/9194191.html

posted @ 2019-08-16 11:10  JamJarBranch  阅读(123)  评论(0编辑  收藏  举报