Loading and rendering templates outside of Django
Using this tutorial as my reference , I wrote a tag pair parser for the Django template that applies to the TWIG set syntax, namely:
{% set someVar %} variableAssignment {% endset %}
I only use Django for this templating system and up to this point I have managed to get the correct imports to render my template correctly. Here is the code I have:
from django.template import Context, Template, Library, Node, TemplateSyntaxError, Variable, VariableDoesNotExist, resolve_variable
from django.template.loader import *
from django.conf import settings
settings.configure(TEMPLATE_DIRS="/my/templates")
register = Library()
class SetValueNode(Node):
def __init__(self, variable, nodelist):
self.variable = variable
self.nodelist = nodelist
def render(self, context):
context[self.variable] = self.nodelist.render(context)
return ""
@register.tag(name="set")
def set_tag(parser, token):
print "set_tag called: parser",parser," token",token
nodelist = parser.parse(("endset",))
parser.delete_first_token()
return SetValueNode(arg, nodelist)
def sendServiceEmail(username, first, last, service, service_tuple):
TEMPLATES_DIR = "/my/templates/"
emailStr = "myemail.html.twig"
print "Opening file :"+TEMPLATES_DIR+emailStr
t = Template(fp.read())
fp.close()
c = Context({
/*Add context from parameters*/
})
msg = t.render(c)
print msg
But I am getting error:
django.template.base.TemplateSyntaxError: 'set_tag' is not a valid tag library: Template library set_tag not found, tried django.templatetags.set_tag
After some research and thinking about it, it seems that the library that django resides in is a "standard" library. I think I need to tell someone (django, Template or .render settings) that I want them to use "Library" and check the library to check if the templatetag is registered. Is there a way to pass this information to Django WITHOUT creating a django app?
source to share
The following information is specific to Django 1.4 You have three options.
Application solution
You need to create an application with a specific structure, but it doesn't have to be a complete django application. Let's say you call itmyapp
Here is the file structure that is required
myapp/
__init__.py
templatetags/
__init__.py
your_library.py
In your main script do the following
from django.conf import settings
from django.template.loader import get_template
# You need to configure Django a bit
settings.configure(
# Access to template tags
INSTALLED_APPS=('myapp', ),
# Access to templates
TEMPLATE_DIRS=(TEMPLATES_DIR, ),
)
template = get_template("myemail.html.twig")
# Prepare context ....
return t.render(context)
Module solution
If you don't want to use such a large framework, it should be possible to create just a module with template tags and pass it to a method django.template.base.add_to_builtins
, see https://github.com/django/django/blob/master/django/template/base.py # L1349 .
Something completely different
Or you can use jinja2 instead http://jinja.pocoo.org/docs/ , but I don't know how the tags work there.
source to share
Thanks for the great advice @zimma. I wanted to provide a complete example of a module load option.
Let's say you have this important template tag to add from read.py
from django import template
register = template.Library()
@register.filter(name='bracewrap')
def bracewrap(value):
return "{" + value + "}"
This is the html template file temp.html:
{{var|bracewrap}}
Finally, here is a Python script that will tie everything together
import django
from django.conf import settings
from django.template import Template, Context
import os
#load your tags
from django.template.loader import get_template
django.template.base.add_to_builtins("read")
# You need to configure Django a bit
settings.configure(
TEMPLATE_DIRS=(os.path.dirname(os.path.realpath(__file__)), ),
)
#or it could be in python
#t = Template('My name is {{ my_name }}.')
c = Context({'var': 'stackoverflow.com rox'})
template = get_template("temp.html")
# Prepare context ....
print template.render(c)
The output will be
{stackoverflow.com rox}
source to share