1

I am sending an email using django-post_office, which renders the subject line using django templates:

subject = engine.from_string(self.template.html_content).render(self.context)

Django templates automatically sets autoescape=True for security, which means if you have an HTML character such as Here's an email it will produce a string with the character escaped: Here's an email.

How can I disable autoescape when using from_string and render in this way to display the email subject appropriately?

An alternative example:

from django.template import engines
template = engines['django'].from_string("My name is {{ my_name }}.")
context = {"my_name": "<FooBar's>"}
print(template.render(context))

Results in:

My name is &lt;FooBar&#x27;s&gt;.
alias51
  • 8,178
  • 22
  • 94
  • 166
  • can you just change the engine option of autoescape to false? – ha-neul Nov 28 '20 at 17:01
  • @ha-neul that would work, but how do you do that for just this one variable? – alias51 Nov 28 '20 at 17:04
  • in https://docs.djangoproject.com/en/3.1/topics/templates/, search ```engine```, it says: ```DjangoTemplates engines accept the following OPTIONS:``` You change it to ```False``` in ```'OPTIONS'``` – ha-neul Nov 28 '20 at 17:05
  • Yes, but that would require an entire reset of the templating engine, which is a security risk. How do I do it in this one context? – alias51 Nov 28 '20 at 17:08
  • just a thought: maybe define a ```custom_from_string``` function may solve your problem – ha-neul Nov 28 '20 at 17:19
  • Thanks, could you show how that would work? I don't know how you would subclass an engine like that. – alias51 Nov 28 '20 at 17:26
  • it seems overkill. iklinac's answer with {{my_name|safe}} sounds like a way to go. – ha-neul Nov 28 '20 at 17:49

1 Answers1

4

You probably just want to escape you string using proper autoescape template tags

{% autoescape off %}
{{ body }}
{% endautoescape %}

or just mark it as safe

"My name is {{ my_name|safe }}.

You can also escape by setting engine.autoescape to False

Ronan Boiteau
  • 9,608
  • 6
  • 34
  • 56
iklinac
  • 14,944
  • 4
  • 28
  • 30
  • Thanks, I guess I could apply `.from_string("{% autoescape off %}My name is {{ my_name }}.{% endautoescape %}")` but it doesn't feel very pythonic. Is there a way I can pass the flag to the constructor for this one template without changing the flag for the entire engine? – alias51 Nov 28 '20 at 17:13
  • 1
    why don't you just mark variable as safe, explicit is better than implicit – iklinac Nov 28 '20 at 17:27