Introduction to the Python Web framework Flask Signaling Mechanism (signals) _python

Source: Internet
Author: User
Tags assert error handling

Signal (signals)

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

Flask provides a number of signals (core signals) and other extensions provide more signals. The signal is used to notify Subscribers, and the Subscriber should not be encouraged to modify the data. Please refer to the documentation for the relevant signal.

The signal relies on the Blinker library.

Hook (hooks)

Flask hooks (usually appear in blueprints or existing methods of the application, such as some built-in adorners, such as before_request) do not require blinker libraries and allow you to change Request objects (requests) or response objects (response). These change the behavior of the application (or blueprint). such as Before_request () adorner.

The signal looks like the hook does the same thing. However, they are different 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. By 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), and signals are used to log events (such as logging).

Create a signal

Because the signal depends on the Blinker library, make sure you have it installed.

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


Copy Code code as follows:

From Blinker import Namespace
My_signals = Namespace ()


Now you can create a new signal like this:


Copy 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 extended developers:

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

Subscribe to Signal

You can subscribe to the signal by using the Connect () method of the signal. The first parameter is the function to invoke when the signal is emitted, and the second parameter is optional, which is used 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 an application that emits signals. When you subscribe to a signal, make sure you also provide a sender, unless you really want to listen for all of the application signals. This is especially true when you are developing an extension.

For example, here is an assistant context manager for variables that can be used to find out which templates are rendered and passed into the template in a unit test:


Copy 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)


You can now easily pair with the test client:


Copy 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 the flask introduces a new parameter to the signal.

In code, all of the rendered templates that flow out of the application app of the With block are now logged to the templates variable. Whenever the template is rendered, it is added to the context of the template object.

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


Copy 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 example above looks like this:


Copy Code code as follows:

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

Send a signal

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


Copy Code code as follows:

Class Model (object):
...

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


Always try to select a suitable sender. If you have a class that emits signals, take self as the sender. If you send a signal from a random function, use the Current_app._get_current_object () as the sender.

An adorner based on signal subscription

In Blinker 1.1 You can easily subscribe to a signal by using the new Connect_via () Adorner:

Copy 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 stencil is successfully rendered, the signal is sent. This signal is called with the template instance template and the context dictionary (named contexts).

Signal Send:

Copy 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 subscriptions:
Copy Code code 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 the signal defined in Flask-user, which is sent when the user successfully logged in.

Send signal:

Copy Code code as follows:

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

The following example tracks the number of logins and logon IP:
Copy Code code as follows:

# 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 ()

Summary

The signal allows you to subscribe securely to them in a flash. For example, these temporary subscriptions are useful for testing. When using a signal, do not let the signal Subscriber (receiver) have an exception because the exception can cause 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.