Django | Adding/changing code in 3rd party packages with monkey patching

Viewed 119

(+/- 3 months experience with Django)

I'm using the django-newsletter package to create and send newsletters to subscribers on my website. It uses a message.html template for which the context is added in the Submission model:

class Submission(models.Model):
    
    # Some irrelevant code, only showing the send_message method below:
 
    def send_message(self, subscription):
        variable_dict = {
            'subscription': subscription,
            'site': Site.objects.get_current(),
            'submission': self,
            'message': self.message,
            'newsletter': self.newsletter,
            'date': self.publish_date,
            'STATIC_URL': settings.STATIC_URL,
            'MEDIA_URL': settings.MEDIA_URL
        }
    
    unescaped_context = get_context(variable_dict, autoescape=False)

    subject = self.message.subject_template.render(
        unescaped_context).strip()
    text = self.message.text_template.render(unescaped_context)

    message = EmailMultiAlternatives(
        subject, text,
        from_email=self.newsletter.get_sender(),
        to=[subscription.get_recipient()],
        headers=self.extra_headers,
    )

    if self.message.html_template:
        escaped_context = get_context(variable_dict)

        message.attach_alternative(
            self.message.html_template.render(escaped_context),
            "text/html"
        )
        # some more code irrelevant to the question
        
        message.send()

Essentially upon Submitting the newsletter, the context is added in variable_dict in the Submission.send_message method.

In order to add more Personalization possibilities I would like to add my own context variables to this. From what I understand is that it's best to use monkey patching to achieve this, but I am not able to access the variable_dict from outside the method itself. Below is my monkey patch code:

## Monkey Patching ##
# monkey_patches.py

DJANGO_NEWSLETTER_CONTEXT_PATCH = True  # adds context to Submission


def monkey_patch():
    if DJANGO_NEWSLETTER_CONTEXT_PATCH:
        from newsletter.models import Submission
        old_send_message = Submission.send_message

        def new_send_message(self, *k, **kw):
            old_send_message(self, *k, **kw)
            # trying to append to variable dict here, but failing:
            print(variable_dict)  # gives error
            # self.send_message.variable_dict['test'] = 'testvalue' # gives error
            # variable_dict['test'] = 'testvalue' # gives error

        Submission.send_message = new_send_message

# apps.py
from django.apps import AppConfig


class SomeAppConfig(AppConfig):
    name = 'SomeApp'

    def ready(self):
        try:
            from SomeApp.monkey_patches import monkey_patch
            monkey_patch()
        except ImportError:
            pass

Would really appreciate some help. Any pointers are welcome.

0 Answers
Related