This post first appeared on Gevin’s blog

Flask Signals get started

Reproduced without permission from Gevin

Introduction to Flask Signals.

1. How to understand Flask Signals

Flask Signal is very simple and easy to use, greatly reducing the coupling of code and making flask-based systems more robust. However, while Flask Signal is easy to get started with, it is not an entry-level feature in Flask development, nor is it something every developer would think to use, largely due to a lack of understanding of the mechanism. Therefore, before using the Flask Signal, first understand what a Flask Signal is.

What is Signal? Flask’s official documentation is so concise that experienced developers can understand it instantly, but beginners can’t, so Gevin extends the description of the official documentation simply: Signal is used to decouple the behavior and business logic of a system by automatically sending a defined Signal when certain behavior is triggered. The business logic or behavior bound to the Signal is automatically executed after receiving the Signal. The business logic bound to the signal can be pre-defined or added later as requirements change. Based on the mechanism of signal, the system is more stable and easy to scale. It also makes the business logic of the system clearer: when an action is triggered, a signal can be sent. All business logic or behavior related to the behavior is automatically triggered, enabling decoupling. Flask Signal, in other words, is an implementation of the observer pattern, and it makes the systems we develop more open and closed.

“Design patterns” are both a classic solution to a typical coding problem and a bit of “jargon”, not something that beginners need to work with, which is why Flask Signal is so different in terms of how experienced developers and beginners understand it. If you understand the nature of Signal, it’s not a problem to use it. If Gevin’s explanation doesn’t make sense to you, you might want to start with the “watcher model”, but Gevin advises not to expose yourself to too many design patterns too soon without accumulating enough code, which is just too soon to grow up.

2. The use of Flask Signals

Flask Signal is easy to use. The official Flask documentation describes the signal in a complicated way, which is not easy to get started. After you understand the Flask Signal, you can learn how to use it easily.

(1) Signal creation

Signal can be created with just three lines of code:


from blinker import Namespace
my_signals = Namespace()
model_saved = my_signals.signal('model-saved')Copy the code

(2) Send the Signal

Send () sends the sender of Signal. The class sender=self, and the class sender=self. Function sender=current_app._get_current_object();


# In case send signal in a class:
class Model(object):.def save(self):
        model_saved.send(self)


# In case send signal in a function:
def save_model(a):. model_saved.send(current_app._get_current_object())Copy the code

The sender() function can add multiple optional arguments in addition to the sender arguments, which are used for signal’s subscribers, as shown in the next section.

(3) Write subscribers to Signal

Signal subscribers are functions that subscribe to a given Signal (such as model_saved above) and are automatically triggered to complete some function when Signal is activated (that is, when the send() function is called to send the Signal). Changing an ordinary function into a subscription function for signal is as simple as adding a decorator. Using signal as an example above, define a subscriber method as follows:


@model_saved.connect_via(app)
def on_model_saved(a):
    # do something ...Copy the code

For large projects where the code organization is more complex, perhaps the app was created while the system was running, the app in the above code could be replaced with current_app._get_CURRENT_object ().

In addition to connect_via, connect can also be used, that is:


@model_saved.connect
def on_model_saved(a):
    # do something ...Copy the code

If the subscriber function has parameters, it needs to be passed as an optional parameter to signal. Send () so that the subscriber function can receive the parameters. Here is a detailed example:


from blinker import Namespace
from . import models

# Define a signal
octblog_signals = Namespace()
post_visited = octblog_signals.signal('post-visited')


# Define a subscriber
@post_visited.connect
def on_post_visited(sender, post, **extra):
    tracker = models.Tracker()
    tracker.post = post

    ...

    tracker.save()

# Emit signal in a function    
def post_detail(slug, is_preview=False):
    post = models.Post.objects.get_or_404(slug=slug, post_type=post_type)
    data['post'] = post

    # do something.# send signal
    if not is_preview:
        signals.post_visited.send(current_app._get_current_object(), post=post)

    ...Copy the code

conclusion

Flask Signal is easy to use, powerful, and most importantly decouples business and behavior, making code logic cleaner and recommended.

I’ll post a simple but complete Flask Signal example on GitHub sometime later, but feel free to leave a comment if you have a good application