Archive
[django] create a formatted string with the Django template system
Problem
In an application I wanted to send formatted HTML emails. For producing the body of the email, I wanted to use the Django template system. The task is very similar to creating a view. The difference is that I don’t want to send back the HTML to the client in the browser but I want to store it in a string.
Solution
The solution is very simple:
from django.template.loader import render_to_string
def email():
context = {'some_key': 'some_value'}
html = render_to_string('APP_NAME/email.html', context)
send_email(html)
This tip is from here.
Jinja2 example for generating a local file using a template
Here I want to show you how to generate an HTML file (a local file) using a template with the Jinja2 template engine.
Python source (proba.py)
#!/usr/bin/env python
import os
from jinja2 import Environment, FileSystemLoader
PATH = os.path.dirname(os.path.abspath(__file__))
TEMPLATE_ENVIRONMENT = Environment(
autoescape=False,
loader=FileSystemLoader(os.path.join(PATH, 'templates')),
trim_blocks=False)
def render_template(template_filename, context):
return TEMPLATE_ENVIRONMENT.get_template(template_filename).render(context)
def create_index_html():
fname = "output.html"
urls = ['http://example.com/1', 'http://example.com/2', 'http://example.com/3']
context = {
'urls': urls
}
#
with open(fname, 'w') as f:
html = render_template('index.html', context)
f.write(html)
def main():
create_index_html()
########################################
if __name__ == "__main__":
main()
Jinja2 template (templates/index.html)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>Proba</title>
</head>
<body>
<center>
<h1>Proba</h1>
<p>{{ urls|length }} links</p>
</center>
<ol align="left">
{% set counter = 0 -%}
{% for url in urls -%}
<li><a href="{{ url }}">{{ url }}</a></li>
{% set counter = counter + 1 -%}
{% endfor -%}
</ol>
</body>
</html>
Resulting output
If you execute proba.py, you will get this output:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>Proba</title>
</head>
<body>
<center>
<h1>Proba</h1>
<p>3 links</p>
</center>
<ol align="left">
<li><a href="http://example.com/1">http://example.com/1</a></li>
<li><a href="http://example.com/2">http://example.com/2</a></li>
<li><a href="http://example.com/3">http://example.com/3</a></li>
</ol>
</body>
</html>
You can find all these files here (GitHub link).
Using Jinja2 for formatting strings
Example 1
from jinja2 import Environment
config = {
'ffmpeg': '/opt/ffmpeg.static/ffmpeg',
'bitrate': '600k',
'width': '480',
'height': '320',
'threads': '2'
}
command = """{{ ffmpeg }} -i {input} -codec:v libx264 -quality good -cpu-used 0
-b:v {{ bitrate }} -profile:v baseline -level 30 -y -maxrate 2000k
-bufsize 2000k -vf scale={{ width }}:{{ height }} -threads {{ threads }} -codec:a libvo_aacenc
-b:a 128k {output}""".replace('\n', ' ')
command = Environment().from_string(command).render(config)
print command
Output:
/opt/ffmpeg.static/ffmpeg -i {input} -codec:v libx264 -quality good -cpu-used 0 -b:v 600k -profile:v baseline -level 30 -y -maxrate 2000k -bufsize 2000k -vf scale=480:320 -threads 2 -codec:a libvo_aacenc -b:a 128k {output}
Here, command is still a template that can be further formatted, e.g.
print command.format(input="movie.avi", output="movie.mp4")
Example 2
Now let’s see a simpler example:
from jinja2 import Environment
print Environment().from_string("Hello {{ name }}!").render(name="Laci")
Output: “Hello Laci!”.
More examples
See https://gist.github.com/warren-runk/1317933.
Update (20130301)
Here I show you how to avoid using jinja2 :) Let’s take the first example above where jinja2 formatting was combined with Python’s string formatting.
Actually, in this example, jinja2 may be an overkill. We can combine old-style formatting and new-style formatting to have the same result:
config = {
'ffmpeg': '/opt/ffmpeg.static/ffmpeg',
'bitrate': '600k',
'width': '480',
'height': '320',
'threads': '2'
}
command = """{ffmpeg} -i %(input)s -codec:v libx264 -quality good -cpu-used 0
-b:v {bitrate} -profile:v baseline -level 30 -y -maxrate 2000k
-bufsize 2000k -vf scale={width}:{height} -threads {threads} -codec:a libvo_aacenc
-b:a 128k %(output)s""".replace('\n', ' ').format(**config)
Now we have a template that can be further formatted in a loop for instance:
print command % {'input': fname, 'output': output}
Thanks bulkan for the tip.
