Email scheduling in django

As we all know (or should), you can use the Django template system to render email bodies:

def email(email, subject, template, context): from django.core.mail import send_mail from django.template import loader, Context send_mail(subject, loader.get_template(template).render(Context(context)), 'from@domain.com', [email,]) 

I have one drawback: to edit the subject and content of the email you need to edit both the view and the template. Although I can justify giving users admin access to the templates, I do not give them access to raw python!

What would be great if you could indicate the blocks in the letter and pull them out separately when you send the email:

 {% block subject %}This is my subject{% endblock %} {% block plaintext %}My body{% endblock%} {% block html %}My HTML body{% endblock%} 

But how would you do that? How would you render just one block at a time?

+7
django email django-templates django-email
source share
3 answers

This is my third working iteration. Assuming you have an email template like this:

 {% block subject %}{% endblock %} {% block plain %}{% endblock %} {% block html %}{% endblock %} 

I reworked the iteration of sending email via the default list, and there are utilities for sending in one email and django.contrib.auth User (one and several). I cover, perhaps more than I need, but there you go.

Perhaps I also moved to the top with Python-love.

 def email_list(to_list, template_path, context_dict): from django.core.mail import send_mail from django.template import loader, Context nodes = dict((n.name, n) for n in loader.get_template(template_path).nodelist if n.__class__.__name__ == 'BlockNode') con = Context(context_dict) r = lambda n: nodes[n].render(con) for address in to_list: send_mail(r('subject'), r('plain'), 'from@domain.com', [address,]) def email(to, template_path, context_dict): return email_list([to,], template_path, context_dict) def email_user(user, template_path, context_dict): return email_list([user.email,], template_path, context_dict) def email_users(user_list, template_path, context_dict): return email_list([user.email for user in user_list], template_path, context_dict) 

As always, if you can improve it, do it.

+11
source share

Just use two patterns: one for the body and one for the object.

0
source share

I could not get template inheritance to work with the {% body %} tags, so I switched to the template as follows:

 {% extends "base.txt" %} {% if subject %}Subject{% endif %} {% if body %}Email body{% endif %} {% if html %}<p>HTML body</p>{% endif %} 

Now we have to make the template three times, but inheritance works correctly.

 c = Context(context, autoescape = False) subject = render_to_string(template_name, {'subject': True}, c).strip() body = render_to_string(template_name, {'body': True}, c).strip() c = Context(context, autoescape = True) html = render_to_string(template_name, {'html': True}, c).strip() 

I also found it necessary to disable autoescape when rendering text other than HTML to avoid escaped text in the email

0
source share

All Articles