An experience of automated emailing for multilingual site


(2 comments)

I know among more than one thousand of our subscribers there are many webmasters, so I write this article to share an experience of sending emails automatically when a post is updated, using Python - Django for a multilingual site.
The key here is that with a large number of recipients, on the other hand the email content for each person is different, therefore it must be sent one by one and sending time lasts up to several minutes, so choosing a point of time to send the emails is important.
When you click the "Save" button in the admin page, a request chain starts with a POST request. We should not send emails during this time but need to wait for the entire request chain finishing and the response returns a successful save message.
But when the request finished, there is no information about the saved post. Therefore, have to retrieve the data in advance, in the operation phase "Save".
We need signals for activities. Usually Django provides the post_save signal, it is sent when a model is saved. But post_save is not suitable in this case because for multilingual model there will be multiple post_save signals sent.

We need to define a signal, for example:

import django.dispatch

# Define ourself signal to get data
signal_notify_data = django.dispatch.Signal(
    providing_args=["request", "obj"]
    )

This signal provides arguments that are request and obj - the post object is being saved.

Then connect a callback function to the signal:

# Connect the callback function to the self-defined signal.
signal_notify_data.connect(
    callback_notify_data, dispatch_uid="some_unique_id_data"
    )

In which the callback function is responsible for receiving data:

def callback_notify_data(sender, request, obj, **kwargs):
    # Declare global variables to pass through functions
    global notify_request
    global notify_obj
    global request_finished_count
    # Reset request-finished count to zero
    request_finished_count = 0
    # Get data
    notify_request = request
    notify_obj = obj

The signal_notify_data signal is sent inside the save_model() method, at which point all the language versions of the model have been saved:

from your_module.signals import signal_notify_data


class YourPostAdmin(SomeBaseAdmin):

    def save_model(self, request, obj, form, change):
        
        # ...
        
        signal_notify_data.send(
sender=None, request=request, obj=obj
)

In general, signal definition is often placed in such a signals submodule.

So we have finished solving the data task. For emailing time, we use the request_finished signal, but the emails are only actually sent after the last request. Its callback function is as follows:

from your_module import your_send_email_function
from django.core.signals import request_finished

    
def callback_notify(sender, **kwargs):
    global notify_request
    global notify_obj
    global request_finished_count
    # Ignore several requests in the chain
    request_finished_count += 1
    """
    We only send emails when the last request finished
    No problem if you choose a number greater than 2
    """
    if request_finished_count > 2:
        # disconnect the signal
        request_finished.disconnect(
            None, dispatch_uid="some_unique_id_send"
            )
        your_send_email_function(notify_request, notify_obj)

To avoid to signal request_finished with every request, it only connects at the time of saving the post:

from your_module.signals import signal_notify_data, callback_notify
from django.core.signals import request_finished


class YourPostAdmin(SomeBaseAdmin):

    def save_model(self, request, obj, form, change):
        
        # ...
        
        signal_notify_data.send(
sender=None, request=request, obj=obj
) request_finished.connect( callback_notify, dispatch_uid="some_unique_id_send" )

And disconnect immediately before sending emails as shown in the callback function above.

The whole signals submodule is as follows:

import django.dispatch
from your_module import your_send_email_function
from django.core.signals import request_finished

# Define ourself signal to get data
signal_notify_data = django.dispatch.Signal(
    providing_args=["request", "obj"]
    )

def callback_notify_data(sender, request, obj, **kwargs):
    # Declare global variables to pass through functions
    global notify_request
    global notify_obj
    global request_finished_count
    # Reset request-finished count to zero
    request_finished_count = 0
    # Get data
    notify_request = request
    notify_obj = obj
    
def callback_notify(sender, **kwargs):
    global notify_request
    global notify_obj
    global request_finished_count
    # Ignore several requests in the chain
    request_finished_count += 1
    """
    We only send emails when the last request finished
    No problem if you choose a number greater than 2
    """
    if request_finished_count > 2:
        # disconnect the signal
        request_finished.disconnect(
            None, dispatch_uid="some_unique_id_send"
            )
        your_send_email_function(notify_request, notify_obj)

# Connect the callback function to the self-defined signal.
signal_notify_data.connect(
    callback_notify_data, dispatch_uid="some_unique_id_data"
    )

Sending emails in this way, even in minutes, will not affect website access and ensure that the post is saved safely before mass emailing.

By the way, I'm sorry to announce that due to the limited number of emails sent per day, if you are a follower currently you have a probability of receiving email when a post/page updated about 50%. We take random probability to ensure equality for everyone.

Currently unrated

Comments

Jim 3 months, 3 weeks ago

I've been browsing on-line more than 3 hours today,
but I by no means discovered any attention-grabbing article like yours.

It's lovely worth sufficient for me. In my view, if all webmasters and bloggers made good content as you did,
the internet will be a lot more helpful than ever before.
I am sure this piece of writing has touched all the internet users, its really really nice article on building up new
blog. I am sure this article has touched all the internet users, its really really nice article
on building up new blog. http://cspan.org

Link | Reply
Currently unrated

buy dnp online 3 months, 3 weeks ago

Hi there to every , for the reason that I am really keen of reading this blog's
post to be updated regularly. It consists of nice data.

Link | Reply
Currently unrated

New Comment

required

required (not published)

optional

required


What is 8 × 5?

required