Python Web Framework flask Signaling Mechanism (signals) Introduction

Source: Internet
Author: User
Signal (signals)

The flask signal (signals, or event hooking) allows a specific sender to notify the Subscriber what has happened (and now that we know what's going on, we can figure out what to do next).

Flask provides a number of signals (core signals) and other extensions to provide more signals. Signals are used to inform subscribers, and Subscribers should not be encouraged to modify data. Refer to the documentation for related signals.

The signal depends on the Blinker library.

Hooks (hooks)

Flask Hooks (often appearing in blueprints or application-existing methods, such as some built-in adorners, such as before_request) do not require a blinker library and allow you to change the request object or the Response object (response). These change the behavior of the application (or blueprint). such as the Before_request () adorner.

The signal looks and hooks do the same thing. However, they differ in the way they work. For example, the core before_request () handler executes in a specific order and can discard the request before returning the response. In contrast, all signal handlers are unordered and do not modify any data.

In general, hooks are used to change behavior (for example, authentication or error handling), while signals are used to record events (such as logging).

Create a signal

Because the signal depends on the Blinker library, make sure that it is installed.

If you want to use the signal in your own application, you can use the Blinker library directly. The most common use case is to name a custom namespace signal. This is also the recommended practice most of the time:


Copy the Code code as follows:


From Blinker import Namespace
My_signals = Namespace ()


Now you can create a new signal like this:


Copy the Code code as follows:


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


This uses a unique signal name and simplifies debugging. You can use the Name property to access the signal name.

For extension developers:

If you are writing a flask extension and you want to gracefully reduce the impact of missing blinker installations, you can do so using the Flask.signals.Namespace class.

Subscribe to Signals

You can use the Connect () method of the signal to subscribe to the signal. The first parameter is the function to be called when the signal is emitted, and the second parameter is optional to determine the sender of the signal. A signal can have multiple subscribers. You can use the disconnect () method to unsubscribe from the signal.

For all core flask signals, the sender is the signal-emitting application. When you subscribe to a signal, make sure that you also provide a sender, unless you really want to listen for all of the app's signals. This is especially true when you develop an extension.

For example, here is a helper context manager for variables that identify which template is rendered and passed into the template in a unit test:


Copy the Code code as follows:


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)


It is now easy to pair with the test client:


Copy the Code code as follows:


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


Make sure that the subscription uses an extra **extra parameter so that your call does not fail when Flask introduces a new parameter to the signal.

In the code, all templates for rendering from the app app with the block are now logged to the templates variable. Whenever a template is rendered, it is added to the context of the template object.

In addition, there is a handy helper method (Connected_to ()), which allows you to temporarily subscribe a function to a signal using its own context manager. Because the context manager's return value cannot be given that way, the list needs to be passed in as a parameter:


Copy the Code code as follows:


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)


The above example looks like this:


Copy the Code code as follows:


templates = []
With Captured_templates (app, templates, **extra):
...
Template, context = Templates[0]

Send Signal

If you want to send a signal, you can do so by calling the Send () method. It accepts a sender as the first parameter and some optional keyword parameters that are forwarded to the signal User:


Copy the Code code as follows:


Class Model (object):
...

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


Always try to choose a suitable sender. If you have a class that sends out a signal, self as the sender. If you send a signal from a random function, take current_app._get_current_object () as the sender.

An adorner based on a signal subscription

You can also easily subscribe to a signal by using the new Connect_via () adorner in Blinker 1.1:
Copy the Code code as follows:


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)

Example

Template rendering

The template_rendered signal is the flask core signal.

When a template is successfully rendered, the signal is sent. This signal is called with the template instance templates and the context dictionary (named context).

Signal sending:
Copy the Code code as follows:


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


Sample subscription:
Copy CodeThe code is as follows:


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)


Account Tracking

USER_LOGGED_IN is a signal defined in the Flask-user, which is sent when the user has successfully logged in.

Send signal:
Copy the Code code as follows:


# Send user_logged_in Signal
User_logged_in.send (Current_app._get_current_object (), User=user)


The following example tracks login times and login IP:
Copy CodeThe code is as follows:


# This code had 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 ()

Summary

Signals allow you to subscribe to them safely in a flash. For example, these temporary subscriptions are useful for testing. When using a signal, do not let the Subscriber (receiver) of the signal have an exception because the exception causes the program to break.

  • Related Article

    Contact Us

    The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

    If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.