I am drafting an email template to users when they successfully updated their passwords.
I used {{ autoescape off }} in the template, which is rendered by using render_to_string().
However, the email content shows the HTML angle brackets directly like this:
Hi <span style='color:blue'>user! </span>
Your password is updated successfully!
I am using Django2.0 and my code looks like this:
views.py
from django.core.mail import send_mail
from django.template.loader import render_to_string
def sendmail(request, title)
email_title = title
email_content = render_to_string('template.html',{'username':request.user.username})
recipient = request.user.email
send_mail(
email_title,
email_content,
'myemail#email.com',
[recipient,],
)
template.html
{{ autoescape off}}
Hi <span style='color:blue'>user! </span>
Your password is updated successfully!
{{ endautoescape }}
Is there anything wrong with my code?
Otherwise, is autoescape always on while using render_to_string()?
This has nothing to do with autoescape, which is for rendering variables (it is also a template tag, so you use it with {% autoescape off %}, not {{ autoescape off }}). It is doing nothing at all in your current template.
Your issue is that you're trying to put HTML into the plain text body of an email.
send_mail expects a plain text message body. If you want to have a HTML body then you need to supply a html_message argument:
send_mail(
email_title,
'', # Empty plain text body - not recommended and you should supply a plain text alternative
'myemail#email.com',
[recipient,],
html_message=email_content, # This will render as HTML
)
Related
I have Django´s Blog APP installed, all working fine, but I need to add posts (via admin) with HTML in the post content field, now, the text area can only read plain text (it doesn´t render HTML).
This is the field:
(models.py)
content = models.TextField()
This is the HTML for this field:
<h6 class="card-text" ><small>{{post.content|slice:":500" |linebreaks |safe}}</small></h6>
Question is: are there special configs for Django/Python in order for the field to render HTML?
The safe tag should already do that... have you tried this:
{% autoescape off %}
{{ post.content }}
{% endautoescape %}
https://code.djangoproject.com/wiki/AutoEscaping
Hope this helps!
I use the 'messages' interface to pass messages to user like this:
request.user.message_set.create(message=message)
I would like to include html in my {{ message }} variable and render it without escaping the markup in the template.
If you don't want the HTML to be escaped, look at the safe filter and the autoescape tag:
safe:
{{ myhtml |safe }}
autoescape:
{% autoescape off %}
{{ myhtml }}
{% endautoescape %}
If you want to do something more complicated with your text you could create your own filter and do some magic before returning the html.
With a templatag file looking like this:
from django import template
from django.utils.safestring import mark_safe
register = template.Library()
#register.filter
def do_something(title, content):
something = '<h1>%s</h1><p>%s</p>' % (title, content)
return mark_safe(something)
Then you could add this in your template file
<body>
...
{{ title|do_something:content }}
...
</body>
And this would give you a nice outcome.
Use the autoescape to turn HTML escaping off:
{% autoescape off %}{{ message }}{% endautoescape %}
You can render a template in your code like so:
from django.template import Context, Template
t = Template('This is your <span>{{ message }}</span>.')
c = Context({'message': 'Your message'})
html = t.render(c)
See the Django docs for further information.
The simplest way is to use the safe filter:
{{ message|safe }}
Check out the Django documentation for the safe filter for more information.
No need to use the filter or tag in template.
Just use format_html() to translate variable to html and Django will automatically turn escape off for you variable.
format_html("<h1>Hello</h1>")
Check out here https://docs.djangoproject.com/en/3.0/ref/utils/#django.utils.html.format_html
The safe filter did the work for me.
Using {{data|safe}} includes the html as it is.
So I want to create a send email function using Templates with Jinja 2.
My specific Issue is that I want to create one template for an email which contains both the subject and the body of the email. For example my template can look like
Subject: This is the Subject
Body: hello I am the body of this email
but I need the subject and body to be saved in different variables to be passed to the sendmail function. My question is , how can I use a single template file and render parts of it in different variables.
You can load a Template, rather than rendering it by using Jinja2's Environment.get_or_select_template method on Flask.jinja_env. Once you have the template, you can access the template's blocks if you don't render it:
some-email.html
{% block subject %}This is the subject: {{ subject_details }}{% endblock %}
{% block body %}
This is the body.
Hello there, {{ name }}!
{% endblock %}
email_handler.py
def generate_email(template_name, **render_args):
"""Usage:
>>> subject, body = generate_email(
'some-email.html',
subject_details="Hello World",
name="Joe")
"""
app.update_template_context(render_args)
template = app.jinja_env.get_or_select_template(template_name)
Context = template.new_context
subject = template.blocks['subject'](Context(vars=render_args))
body = template.blocks['body'](Context(vars=render_args))
return subject, body
def send_email(template_name, **render_args):
subject, body = generate_email(template_name, **render_args)
# Send email with subject and body
I process a string on the server using python markdown2 module.
marked_up = ' import sys\n print "hello there"'
marked_up = unicode(markdown2.markdown(marked_up, extras=["fenced-code-blocks"]))
Then, I pass the value through jinja2 to the client:
template_value = {'marked_up': marked_up}
template = JINJA_ENVIRONMENT.get_template('index.html')
self.response.write(template.render(template_value))
In the index.html I try to display this marked value:
<div class="row marketing" id="my_row_mark">
{{ marked_up }}
</div>
The problem is that the text is shown with the html attributes:
<pre><code>import sys print "hello there" </code></pre>
I would like to see only:
import sys print "hello there"
with the proper markdown applied by markdown2.
TL;DR:
Use the |safe filter to prevent your content from getting automatically escaped:
{{ marked_up|safe }}
Jinja2 has a configuration option named autoescape that determines if content in templates should be automatically HTML escaped or not.
By default (if you're using plain Jinja2) autoescaping is disabled. But if your using a framework that integrates Jinja2, autoescape may very well be enabled.
So when autoescaping is enabled, any content you pass into a template will be HTML escaped. Note in this example how content will be escaped, which leads to you seeing the HTML tags in the rendered HTML:
example.py
from jinja2 import Environment, FileSystemLoader
env = Environment(loader=FileSystemLoader('.'),
autoescape=True) # <-- autoescaping enabled
template = env.get_template('index.html')
content = "<strong>bar</strong>"
print template.render(content=content)
index.html
<div>
{{ content }}
</div>
Output:
<div>
<strong>bar</strong>
</div>
You can now prevent escaping for a particular variable by using the |safe filter:
<div>
{{ content|safe }}
</div>
Output:
<div>
<strong>bar</strong>
</div>
For more details, see the documentation on HTML escaping.
Quick question. If I have a form that sends to email, is there a way to make some of the sent text show up bold in the email?
In Django 1.7, send_mail() accepts an html_message argument:
If html_message is provided, the resulting email will be
a multipart/alternative email with message as the text/plain content
type and html_message as the text/html content type.
Example:
send_mail('Subject', 'Content', 'sender#example.com', ['nobody#example.com'],
html_message='This is <b>HTML</b> Content')
For Django<1.7, you can either use a solution suggested here, or use a third-party, like django-email-html.
Also, there is another third-party package that you should consider using - django-mail-templated. It basically allows you to describe your email messages in django templates. Additionally, it allows to send html messages defined in html block in the template.
For example:
create a template
{% block subject %}
Email subject
{% endblock %}
{% block body %}
This is a plain text.
{% endblock %}
{% block html %}
This is <b>HTML</b> Content.
{% endblock %}
and send it:
from mail_templated import send_mail
send_mail('my_template.tpl', {}, from_email, [user.email])
Hope that helps.