Last active
March 28, 2016 19:05
-
-
Save jessykate/f33db26aa709b0723cd2 to your computer and use it in GitHub Desktop.
A Django pattern for creating customizable, re-useable email templates. Admins can define a number of standard templates, and these templates are then injected into email forms as default content, which can then be selected from and customized on the fly before being sent.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Models.py | |
class EmailTemplate(models.Model): | |
''' Templates for standard emails. ''' | |
body = models.TextField(verbose_name="The body of the email") | |
subject = models.CharField(max_length=200, verbose_name="Default Subject Line") | |
name = models.CharField(max_length=200, verbose_name="Template Name") | |
creator = models.ForeignKey(User) | |
# Forms.py | |
class EmailTemplateForm(forms.Form): | |
''' We don't actually make this a model form even though it's a derivative | |
function of a model because it's not directly constructed from the model fields | |
itself. | |
Separating out a base form means multiple derivative types of EmailTemplateForms | |
can be created for different contexts. | |
''' | |
sender = forms.EmailField(widget=forms.TextInput(attrs={'readonly':'readonly', 'class':"form-control"})) | |
recipient = forms.EmailField(widget=forms.TextInput(attrs={'class':"form-control"})) | |
footer = forms.CharField( widget=forms.Textarea(attrs={'readonly':'readonly', 'class':"form-control"})) | |
subject = forms.CharField(widget=forms.TextInput(attrs={'class':"form-control"})) | |
body = forms.CharField(widget=forms.Textarea(attrs={'class':"form-control"})) | |
class EventEmailTemplateForm(EmailTemplateForm): | |
def __init__(self, tpl, subscription, location): | |
''' pass in an EmailTemplate instance, and an whatever else you need to construct the default content. | |
In this case, I'm using a subscription object. ''' | |
domain = Site.objects.get_current().domain | |
# calling super will initialize the form fields | |
super(SubscriptionEmailTemplateForm, self).__init__() | |
# add in the default content for each of the fields. these will all be editable | |
# by the user (except the readonly field) because it is just default content in | |
# a form field. | |
self.fields['sender'].initial = location.from_email() | |
# in our case we always cc the admin email, of course this is optional. | |
self.fields['recipient'].initial = "%s, %s" % (subscription.user.email, location.from_email()) | |
# make the footer field readonly because we don't want the users editing that part. | |
self.fields['footer'].initial = forms.CharField( | |
widget=forms.Textarea(attrs={'readonly':'readonly'}) | |
) | |
self.fields['footer'].initial = '''--------------------------------\nYour membership id is %d. Manage your membership from your profile page https://%s/people/%s.''' % (subscription.id, domain, subscription.user.username) | |
template_variables = { | |
'subscription': subscription, | |
} | |
self.fields['subject'].initial = '['+location.email_subject_prefix+'] ' + Template(tpl.subject).render(Context(template_variables)) + ' (#' + str(subscription.id) + ')' | |
self.fields['body'].initial = Template(tpl.body).render(Context(template_variables)) | |
# Views.py | |
def SomeView(request, ...): | |
# do stuff... | |
default_email = SubscriptionEmailTemplateForm(email_template, subscription, location) | |
# do other stuff, then pass the form to the context for rendering | |
return render(request, 'subscription_manage.html', {'default_email': default_email, ... }) | |
# Some_Template.html | |
<form id="action-email-user" method=POST action="{% url 'subscription_send_mail' location.slug s.id %}"> | |
{% csrf_token %} | |
<div class="form-group"> | |
<span class="email-form-label">To: </span> {{f.recipient}} <br> | |
<span class="email-form-label">From: </span> {{f.sender}} <br> | |
<span class="email-form-label">Subject: </span> {{f.subject}} <br> | |
{{f.body}} | |
{{f.footer}} | |
</div> | |
<submit value="Send"> | |
<button class="btn" data-dismiss="modal" aria-hidden="true">Cancel</button> | |
<button type="submit" class="btn btn-primary">Send Email</button> | |
</form> | |
# use whatever method you prefer to process the actual sending of email on the submit view. We use Mailgun. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment