国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

腳本之家,腳本語言編程技術及教程分享平臺!
分類導航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服務器之家 - 腳本之家 - Python - Python Web框架Flask信號機制(signals)介紹

Python Web框架Flask信號機制(signals)介紹

2020-05-18 09:54腳本之家 Python

這篇文章主要介紹了Python Web框架Flask信號機制(signals)介紹,本文介紹Flask的信號機制,講述信號的用途,并給出創建信號、訂閱信號、發送信號的方法,需要的朋友可以參考下

信號(signals)

 

Flask信號(signals, or event hooking)允許特定的發送端通知訂閱者發生了什么(既然知道發生了什么,那我們可以知道接下來該做什么了)。

Flask提供了一些信號(核心信號)且其它的擴展提供更多的信號。信號是用于通知訂閱者,而不應該鼓勵訂閱者修改數據。相關信號請查閱文檔。

信號依賴于Blinker庫。

 

鉤子(hooks)

 

Flask鉤子(通常出現在藍圖或應用程序現存的方法中,比如一些內置裝飾器,例如before_request)不需要Blinker庫并且允許你改變請求對象(request)或者響應對象(response)。這些改變了應用程序(或者藍圖)的行為。比如before_request()裝飾器。

 

信號看起來和鉤子做同樣的事情。然而在工作方式上它們存在不同。譬如核心的before_request()處理程序以特定的順序執行,并且可以在返回響應之前放棄請求。相比之下,所有的信號處理器是無序執行的,并且不修改任何數據。

 

一般來說,鉤子用于改變行為(比如,身份驗證或錯誤處理),而信號用于記錄事件(比如記錄日志)。

 

創建信號

 

因為信號依賴于Blinker庫,請確保已經安裝。

如果你要在自己的應用中使用信號,你可以直接使用Blinker庫。最常見的使用情況是命名一個自定義的Namespace的信號。這也是大多數時候推薦的做法:

 

復制代碼 代碼如下:

from blinker import Namespace
my_signals = Namespace()

 


現在你可以像這樣創建新的信號:

 

復制代碼 代碼如下:

model_saved = my_signals.signal('model-saved')

 


這里使用唯一的信號名并且簡化調試。可以用name屬性來訪問信號名。

 

對擴展開發者:

 

如果你正在編寫一個Flask擴展,你想優雅地減少缺少Blinker安裝的影響,你可以這樣做使用flask.signals.Namespace類。

 

訂閱信號

 

你可以使用信號的connect()方法來訂閱信號。第一個參數是信號發出時要調用的函數,第二個參數是可選的,用于確定信號的發送者。一個信號可以擁有多個訂閱者。你可以用disconnect()方法來退訂信號。

 

對于所有的核心Flask信號,發送者都是發出信號的應用。當你訂閱一個信號,請確保也提供一個發送者,除非你確實想監聽全部應用的信號。這在你開發一個擴展的時候尤其正確。

 

比如這里有一個用于在單元測試中找出哪個模板被渲染和傳入模板的變量的助手上下文管理器:

 

復制代碼 代碼如下:


from flask import template_rendered
from contextlib import contextmanager

 

@contextmanager
def captured_templates(app):
    recorded = []
    def record(sender, template, context, **extra):
        recorded.append((template, context))
    template_rendered.connect(record, app)
    try:
        yield recorded
    finally:
        template_rendered.disconnect(record, app)

 


現在可以輕松地與測試客戶端配對:

 

復制代碼 代碼如下:

with captured_templates(app) as templates:
    rv = app.test_client().get('/')
    assert rv.status_code == 200
    assert len(templates) == 1
    template, context = templates[0]
    assert template.name == 'index.html'
    assert len(context['items']) == 10

 


確保訂閱使用了一個額外的 **extra 參數,這樣當 Flask 對信號引入新參數時你的調用不會失敗。

 

代碼中,從 with 塊的應用 app 中流出的渲染的所有模板現在會被記錄到templates 變量。無論何時模板被渲染,模板對象的上下文中添加上它。

 

此外,也有一個方便的助手方法(connected_to()) ,它允許你臨時地用它自己的上下文管理器把函數訂閱到信號。因為上下文管理器的返回值不能按那種方法給定,則需要把列表作為參數傳入:

 

復制代碼 代碼如下:


from flask import template_rendered

 

def captured_templates(app, recorded, **extra):
    def record(sender, template, context):
        recorded.append((template, context))
    return template_rendered.connected_to(record, app)

 


上面的例子看起來像這樣:

 

復制代碼 代碼如下:

templates = []
with captured_templates(app, templates, **extra):
    ...
    template, context = templates[0]

 

 

發送信號

 

如果你想要發送信號,你可以通過調用 send() 方法來達到目的。它接受一個發件者作為第一個參數和一些可選的被轉發到信號用戶的關鍵字參數:

 

復制代碼 代碼如下:


class Model(object):
    ...

 

    def save(self):
        model_saved.send(self)

 


永遠嘗試選擇一個合適的發送者。如果你有一個發出信號的類,把 self 作為發送者。如果你從一個隨機的函數發出信號,把current_app._get_current_object()作為發送者。

 

基于信號訂閱的裝飾器

 

在Blinker 1.1中通過使用新的connect_via()裝飾器你也能夠輕易地訂閱信號:

復制代碼 代碼如下:


from flask import template_rendered

 

@template_rendered.connect_via(app)
def when_template_rendered(sender, template, context, **extra):
    print 'Template %s is rendered with %s' % (template.name, context)

 

 

舉例

 

模板渲染

 

template_rendered信號是Flask核心信號。

當一個模版成功地渲染,這個信號會被發送。這個信號與模板實例 template 和上下文的詞典(名為 context )一起調用。

信號發送:

復制代碼 代碼如下:

def _render(template, context, app):
    """Renders the template and fires the signal"""
    rv = template.render(context)
    template_rendered.send(app, template=template, context=context)
    return rv


訂閱示例:

復制代碼 代碼如下:


def log_template_renders(sender, template, context, **extra):
    sender.logger.debug('Rendering template "%s" with context %s',
                        template.name or 'string template',
                        context)

 

from flask import template_rendered
template_rendered.connect(log_template_renders, app)

 


帳號追蹤

 

user_logged_in是Flask-User中定義的信號,當用戶成功登入之后,這個信號會被發送。

發送信號:

復制代碼 代碼如下:

# Send user_logged_in signal
user_logged_in.send(current_app._get_current_object(), user=user)


下面這個例子追蹤登錄次數和登錄IP:

復制代碼 代碼如下:


# This code has not been tested

 

from flask import request
from flask_user.signals import user_logged_in

@user_logged_in.connect_via(app)
def _track_logins(sender, user, **extra):
    user.login_count += 1
    user.last_login_ip = request.remote_addr
    db.session.add(user)
    db.session.commit()

 

 

小結

 

信號可以讓你在一瞬間安全地訂閱它們。例如,這些臨時的訂閱對測試很有幫助。使用信號時,不要讓信號訂閱者(接收者)發生異常,因為異常會造成程序中斷。

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 亚洲男人av| 99热99 | 免费三级国产 | 成人精品99| 午夜欧美精品久久久久 | 午夜色播| 久热免费视频 | 亚洲色视频 | 欧美精品三区 | 五月婷婷在线视频 | 99精品国产高清在线观看 | 国产精品美女久久久久久久久久久 | 午夜免费小视频 | 高清18麻豆 | 国产色网 | 久久久免费精品视频 | 久久精品视频免费观看 | 日本在线观看 | 国产精品亚洲综合 | 中文字幕在线观看 | 日韩中文一区二区三区 | 99热首页 | 久久久久久九九九 | 丝袜+亚洲+另类+欧美+变态 | 九九热在线观看 | 亚洲精品国产片 | 一区二区三区在线免费视频 | 伊人久久精品久久亚洲一区 | 综合九九| 国产精品欧美久久久久久 | 欧美一区二 | 免费国产一区二区 | 国产精品成人在线观看 | 国产在线专区 | 欧美在线观看免费观看视频 | 欧美国产日韩在线 | 一级欧美在线 | 精品一二三区 | 国产成人精品久久二区二区 | 人人做人人澡人人爽欧美 | av免费网|