請求上下文、g對象、flask_session、信號、自定義命名

flask之請求上下文、g對象、flask_session、信號、自定義命名

一、local與偏函數

一、local內部實現原理

import time
from threading import Thread,local,get_ident

#####這是使用local對象
# a = local()
# #
# # def task(arg):
# #     a.value = arg
# #
# #     time.sleep(1)
# #
# #     print(a.value)

#####用函數的形式來模擬local
# storage = {}
# def set(k,v):
#     # 獲取線程id
#     ident = get_ident()
#     if ident in storage:
#         storage[ident][k]=v
#     else:
#         storage[ident] = {k:v}
#
# def get(k):
#     ident = get_ident()
#     return storage[ident][k]
#
# def task(arg):
#     set('val',arg)
#     time.sleep(1)
#     v = get("val")
#     print(v)


#面向對象版1

# class Local:
#     storage ={}
#     def set(self,k,v):
#         ident = get_ident()
#         if ident in Local.storage:
#             Local.storage[ident][k] = v
#         else:
#             Local.storage[ident] = {k:v}
#
#     def get(self,k):
#         ident = get_ident()
#         return Local.storage[ident][k]
#
# obj = Local()
# def task(arg):
#     obj.set("val",arg)
#     time.sleep(1)
#     v = obj.get("val")
#     print(v)

# #面向對象的setattr,getattr版
# class Local:
#     storage ={}
#     def __setattr__(self,k,v):
#         ident = get_ident()
#         if ident in Local.storage:
#             Local.storage[ident][k] = v
#         else:
#             Local.storage[ident] = {k:v}
#
#     def __getattr__(self,k):
#         ident = get_ident()
#         return Local.storage[ident][k]

# obj = Local()
# # def task(arg):
# #     obj.val=arg
# #     time.sleep(1)
# #     print(obj.val)

# 面向對象,將storage變成對象的屬性
class Local(object):
    def __init__(self):
        #防止getattr遞歸
        object.__setattr__(self,"storage",{})
        #self.storage = {}
    def __setattr__(self,k,v):
        ident = get_ident()
        if ident in self.storage:
            self.storage[ident][k] = v
        else:
            self.storage[ident] = {k:v}

    def __getattr__(self,k):
        ident = get_ident()
        return self.storage[ident][k]


obj = Local()
def task(arg):
    obj.val=arg
    time.sleep(1)
    print(obj.val)

for i in range(10):
    t = Thread(target=task,args=(i,))
    t.start()

二、偏函數

第一個參數是函數的對象,第二個到後面都是函數的參數,嚴格按照python函數的傳參規則python

#偏函數partial
from functools import partial

def fun(a,b,c,d):

    return a+b+c+d

#第一個參數是函數的對象,第二個到後面都是函數的參數,嚴格按照python函數的傳參規則
tes = partial(fun,a=1,b=2)
tes1 = partial(tes,c=3)
print(tes) # 獲得partial對象
print(tes1(d=4)) # 10

二、請求上下文實現原理

三、g對象

g對象是global是當前請求的全局設置變量,其餘的請求時沒法獲得的,專門用來存儲用戶信息的g對象redis

咱們不用request請求來設置由於request中有不少屬性,防止設置的屬性與request屬性衝突改變了request中的屬性數據庫

通常用g對象在before_request中設置屬性給當次請求的響應函數來使用django

#g ,global,當前請求的全局,
#g,對象只當前請求內有效,一旦不是一個請求,就不能獲取
from flask import Flask,g,request

app = Flask(__name__)

@app.before_request
def befor():
    #你知道request裏面有哪些?
    #g 它就怕你和全局request改變了它裏面的屬性
    # 通常在before_request中使用攜帶參數給視圖函數
    g.name = "tank"

@app.route("/")
def index():

    print(g.name)
    return "ok"

@app.route("/index")
def index1():
    #print(g.name) # 根路徑下獲取了,此處沒法獲取
    return "ok1"

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

四、flask_session

將默認保存的簽名cookie中的值 保存到 redis/memcached/file/Mongodb/SQLAlchemyflask

一、下載模塊 瀏覽器

pip install flask-session

二、從flask_session中導入要存的數據庫cookie

from flask_session import RedisSessionInterface
from flask import Flask,session
from flask_session import RedisSessionInterface
import redis
app = Flask(__name__)
conn=redis.Redis(host='127.0.0.1',port=6379, password=2694)
app.secret_key = "123"
#permanent=True,若是這個值爲True,表示關閉瀏覽器,不失效,若是爲Fasle,表示關閉瀏覽器,session就失效
app.session_interface=RedisSessionInterface(conn,key_prefix='lqz',use_signer=True)

@app.route('/')
def hello_world():
    session['name']='lqz'
    return 'Hello World!'

@app.route("/index")
def index():
    print(session['name'])
    return "ok"

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

三、通常用法是在app中配置數據庫後直接導入Sessionsession

from redis import Redis
from flask import Flask,session
from flask_session import Session
app = Flask(__name__)

app.config['SESSION_TYPE'] = 'redis'

app.config['SESSION_REDIS'] = Redis(host='127.0.0.1',port='6379', password='2694')

Session(app)

@app.route("/")
def index():
    session['name'] = "tank"
    return "ok"

@app.route("/index")
def index1():
    print(session['name'])
    return "ok"

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

五、信號

一、下載模塊app

pip install blinker

二、設置觸發信號的執行函數ide

三、設置信號觸發點

request_started = _signals.signal('request-started')                # 請求到來前執行
request_finished = _signals.signal('request-finished')              # 請求結束後執行
 
before_render_template = _signals.signal('before-render-template')  # 模板渲染前執行
template_rendered = _signals.signal('template-rendered')            # 模板渲染後執行
 
got_request_exception = _signals.signal('got-request-exception')    # 請求執行出現異常時執行
 
request_tearing_down = _signals.signal('request-tearing-down')      # 請求執行完畢後自動執行(不管成功與否)
appcontext_tearing_down = _signals.signal('appcontext-tearing-down')# 應用上下文執行完畢後自動執行(不管成功與否)
 
appcontext_pushed = _signals.signal('appcontext-pushed')            # 應用上下文push時執行
appcontext_popped = _signals.signal('appcontext-popped')            # 應用上下文pop時執行
message_flashed = _signals.signal('message-flashed')                # 調用flask在其中添加數據時,自動觸發

使用:

from flask import Flask,signals

app = Flask(__name__)

#觸發信號要執行函數
def si(*args,**kwargs):
    print("觸發這個信號",args,kwargs)

# 觸發信號點
signals.request_started.connect(si)

@app.route("/")
def index():
    return "123"

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

自定義信號(瞭解)

from flask import Flask
from flask.signals import _signals

app = Flask(__name__)

# 自定義信號
xxxxx = _signals.signal('xxxxx')


# 接收參數的時候,就算send方法不傳,也要接收一個參數,後面按照關鍵字接收參數
def func(arg,on1):
    print("123123",arg,on1)


# 自定義信號中註冊函數
xxxxx.connect(func)


@app.route("/x")
def index():
    # 觸發信號 #傳參的時候,一個必須是位置參數,後面的產生必須是關鍵字參數
    xxxxx.send("sb",on1="sb2")
    return 'Index'


if __name__ == '__main__':

    app.run()

六、自定義命令 flask-script

用於實現相似於django中 python3 manage.py runserver ...相似的命令

一、下載模塊

pip install flask-script

二、使用

from flask_script import Manager
app = Flask(__name__)
manager=Manager(app)
...
if __name__ == '__main__':
    manager.run()
#之後在執行,直接:python3 manage.py runserver
#python3 manage.py runserver --help
@manager.command
def custom(arg):
    """
    自定義命令
    python manage.py custom 123
    :param arg:
    :return:
    """
    print(arg)


@manager.option('-n', '--name', dest='name')
#@manager.option('-u', '--url', dest='url')
def cmd(name, url):
    """
    自定義命令(-n也能夠寫成--name)
    執行: python manage.py  cmd -n lqz -u http://www.oldboyedu.com
    執行: python manage.py  cmd --name lqz --url http://www.oldboyedu.com
    :param name:
    :param url:
    :return:
    """
    print(name, url)
自定義命令
相關文章
相關標籤/搜索