Define email subject in a Django template
Question:
Say I want to send an email using the send_mail()
method. The body of the email lives in templates/email.html. I would like to define the email subject in the same file to keep things in one place.
But send_mail()
needs the subject in a separate variable.
So I came up with an ugly hacky way to do it. I start the template like this:
{% comment "The second line of this template will be used as email subject" %}
Congratulations, your account was created!
{% endcomment %}
And then extract it in the code like this:
template = loader.get_template('email.html')
subject = template.template.source.splitlines()[1]
This works, but I dislike this solution. Is there an easier and more readable way to do this?
More generally, can I define a variable in Django template and then extract it in the application? Something like template.get_variable("email_subject")
?
Answers:
I would do this the way Django does by having two separate templates, one for the subject and one for the body.
subject = loader.render_to_string(subject_template_name, context)
# Email subject *must not* contain newlines
subject = "".join(subject.splitlines())
body = loader.render_to_string(email_template_name, context)
You can see an example in Django’s codebase for their forgot password email https://github.com/django/django/blob/9ac3ef59f9538cfb520e3607af743532434d1755/django/contrib/auth/forms.py#L274
I have tried a solutions for this type of problem and its working for me.
- I have model definition like
subject_line = models.TextField(null=True, blank=True, help_text=_("Initially used as email subject line.")
- Then I populated it with the following templates
{% load i18n %}{% autoescape off %}
{% blocktranslate %} Confirmation for order number:{{order_number}}, order reference:{{order_reference}}, po nummer:{{po_number}}, customer reference:{{customer_reference}} {% endblocktranslate %}
{% endautoescape %}
- Updated the related logics like
from django.template import Context, Template
subject_context = {
"order_reference": order.reference,
"order_number": order.id,
"po_number": order.po_number,
"customer_reference": order.customer_reference,
}
subject_context_obj = Context(subject_context)
email_subject_template_obj =Template(email_template_obj.subject_line)
subject = email_subject_template_obj.render(context=subject_context_obj)
subject = "".join(subject.splitlines()).strip()
email = EmailMessage(
subject=subject,
body=body,
to=to_email
)
- The subject is become
Confirmation for Order Number:886, Order Reference:H00000886, PO Number:PO-1234, Customer Reference:Sharif 1234
Say I want to send an email using the send_mail()
method. The body of the email lives in templates/email.html. I would like to define the email subject in the same file to keep things in one place.
But send_mail()
needs the subject in a separate variable.
So I came up with an ugly hacky way to do it. I start the template like this:
{% comment "The second line of this template will be used as email subject" %}
Congratulations, your account was created!
{% endcomment %}
And then extract it in the code like this:
template = loader.get_template('email.html')
subject = template.template.source.splitlines()[1]
This works, but I dislike this solution. Is there an easier and more readable way to do this?
More generally, can I define a variable in Django template and then extract it in the application? Something like template.get_variable("email_subject")
?
I would do this the way Django does by having two separate templates, one for the subject and one for the body.
subject = loader.render_to_string(subject_template_name, context)
# Email subject *must not* contain newlines
subject = "".join(subject.splitlines())
body = loader.render_to_string(email_template_name, context)
You can see an example in Django’s codebase for their forgot password email https://github.com/django/django/blob/9ac3ef59f9538cfb520e3607af743532434d1755/django/contrib/auth/forms.py#L274
I have tried a solutions for this type of problem and its working for me.
- I have model definition like
subject_line = models.TextField(null=True, blank=True, help_text=_("Initially used as email subject line.")
- Then I populated it with the following templates
{% load i18n %}{% autoescape off %}
{% blocktranslate %} Confirmation for order number:{{order_number}}, order reference:{{order_reference}}, po nummer:{{po_number}}, customer reference:{{customer_reference}} {% endblocktranslate %}
{% endautoescape %}
- Updated the related logics like
from django.template import Context, Template
subject_context = {
"order_reference": order.reference,
"order_number": order.id,
"po_number": order.po_number,
"customer_reference": order.customer_reference,
}
subject_context_obj = Context(subject_context)
email_subject_template_obj =Template(email_template_obj.subject_line)
subject = email_subject_template_obj.render(context=subject_context_obj)
subject = "".join(subject.splitlines()).strip()
email = EmailMessage(
subject=subject,
body=body,
to=to_email
)
- The subject is become
Confirmation for Order Number:886, Order Reference:H00000886, PO Number:PO-1234, Customer Reference:Sharif 1234