I have Django templates written in Markdown. I'd like to implement template tag to include rendered markdown.
{% include_md 'mytemplate.md' }
I wrote template tag to render my template:
import markdown
from django.template import Library, loader, Context
#register.simple_tag(takes_context=True)
def include_md(context, template_name):
t = loader.get_template(template_name)
return t.render(Context({
#...
}))
but I need to put somewhere in the middle of my function something like:
markdown.markdown(template_content)
Unfortunately, template loader doesn't return content of template. So what is a best way to achieve rendering? I woudln't like to implement my own opening template methods with open().
Django provides a convenience method render_to_string for situations like this:
from django.template.loader import render_to_string
#register.simple_tag(takes_context=True)
def include_md(context, template_name):
template = render_to_string(template_name, context)
return markdown.markdown(template)
This question is similar to Testing a custom Django template filter, but unlike in that example, the filter is actually defined in a module in the templatetags directory as described in https://docs.djangoproject.com/en/2.0/howto/custom-template-tags/#writing-custom-template-filters. Here is the filter code in templatetags/label_with_classes.py:
from django import template
register = template.Library()
#register.filter(is_safe=True)
def label_with_classes(bound_field):
classes = f"{'active' if bound_field.value() else ''} {'invalid' if bound_field.errors else ''}"
return bound_field.label_tag(attrs={'class': classes})
Here is my first stab at a test for it:
from ..templatetags.label_with_classes import label_with_classes
from django.test import SimpleTestCase
from django.template import Context, Template
from ..forms.sessions import SessionForm
class CustomFilterTest(SimpleTestCase):
def test_1(self):
form = SessionForm(data={})
self.assertFalse(form.is_valid())
self.assertEqual(
form.errors,
{'session_number': ['This field is required.'],
'family': ['This field is required.'],
'session_type': ['This field is required.']})
template = Template('{{ form.session_number|label_with_classes }}')
context = Context({'form': form})
output = template.render(context)
The problem is that I get an error that the filter was not found:
django.template.exceptions.TemplateSyntaxError: Invalid filter: 'label_with_classes'
This is because the test case doesn't mimic the behavior of registering the filter and loading it in the template. It seems like in the Django source code, for example https://github.com/django/django/blob/master/tests/template_tests/filter_tests/test_join.py, there is an elaborate setup decorator which provides the test class with a self.engine whose render_to_string method has the required filters already installed.
Do I basically have to copy the Django source code to write an integration-style test for my custom filter? Or is there a simpler way (besides just testing it as a function)?
I suspect you need to load your template module:
...
template = Template("""{% load label_with_classes %}
{{ form.session_number|label_with_classes }}""")
...
See the relevant documentation.
When returning an HttpResponse object with render_to_response you can provide a template and it will use that template and fill in all the {{ variables }} you've set within your template.
If I want to build my HttpResponse object manually, is it possible to still use one of my templates in my template directory?
Using render_to_string, you will get rendered string. You can pass the returned string to the HttpResponse.
from django.template.loader import render_to_string
...
rendered = render_to_string('my_template.html', {'foo': 'bar'})
response = HttpResponse(rendered)
Yes - you can use Django's template loader to load your template as a Template object, and then render it to a string, which you pass to HttpResponse:
from django.template import Template, Context
from django.template.loader import get_template
def my_view(request):
temp = get_template('/path/to/template.html')
result = temp.render(Context({'context': 'here'})
return HttpResponse(result)
EDIT
Just noticed #falsetru's answer above - that's probably a better and shorter way!
I want to pass value of a variable from template to a templatetag but in the token list I get picture.uri as a string [u'thumbnail', u'picture.uri']
{% thumbnail picture.uri %}
Templatetag code:
from django.template import Library
register = Library()
#register.tag()
def thumbnail(parser, token):
...
...
How to pass variable value to a templatetag?
Sultan
It is very well-documented
But I recommend to use some framework for creating tags, I use this.
I want to use the Django template engine in my (Python) code, but I'm not building a Django-based web site. How do I use it without having a settings.py file (and others) and having to set the DJANGO_SETTINGS_MODULE environment variable?
If I run the following code:
>>> import django.template
>>> from django.template import Template, Context
>>> t = Template('My name is {{ my_name }}.')
I get:
ImportError: Settings cannot be imported, because environment variable DJANGO_SETTINGS_MODULE is undefined.
The solution is simple. It's actually well documented, but not too easy to find. (I had to dig around -- it didn't come up when I tried a few different Google searches.)
The following code works:
>>> from django.template import Template, Context
>>> from django.conf import settings
>>> settings.configure()
>>> t = Template('My name is {{ my_name }}.')
>>> c = Context({'my_name': 'Daryl Spitzer'})
>>> t.render(c)
u'My name is Daryl Spitzer.'
See the Django documentation (linked above) for a description of some of the settings you may want to define (as keyword arguments to configure).
Jinja2 syntax is pretty much the same as Django's with very few differences, and you get a much more powerfull template engine, which also compiles your template to bytecode (FAST!).
I use it for templating, including in Django itself, and it is very good. You can also easily write extensions if some feature you want is missing.
Here is some demonstration of the code generation:
>>> import jinja2
>>> print jinja2.Environment().compile('{% for row in data %}{{ row.name | upper }}{% endfor %}', raw=True)
from __future__ import division
from jinja2.runtime import LoopContext, Context, TemplateReference, Macro, Markup, TemplateRuntimeError, missing, concat, escape, markup_join, unicode_join
name = None
def root(context, environment=environment):
l_data = context.resolve('data')
t_1 = environment.filters['upper']
if 0: yield None
for l_row in l_data:
if 0: yield None
yield unicode(t_1(environment.getattr(l_row, 'name')))
blocks = {}
debug_info = '1=9'
Any particular reason you want to use Django's templates? Both Jinja and Genshi are, in my opinion, superior.
If you really want to, then see the Django documentation on settings.py. Especially the section "Using settings without setting DJANGO_SETTINGS_MODULE". Use something like this:
from django.conf import settings
settings.configure (FOO='bar') # Your settings go here
An addition to what other wrote, if you want to use Django Template on Django > 1.7, you must give your settings.configure(...) call the TEMPLATES variable and call django.setup() like this :
from django.conf import settings
settings.configure(TEMPLATES=[
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': ['.'], # if you want the templates from a file
'APP_DIRS': False, # we have no apps
},
])
import django
django.setup()
Then you can load your template like normally, from a string :
from django import template
t = template.Template('My name is {{ name }}.')
c = template.Context({'name': 'Rob'})
t.render(c)
And if you wrote the DIRS variable in the .configure, from the disk :
from django.template.loader import get_template
t = get_template('a.html')
t.render({'name': 5})
Django Error: No DjangoTemplates backend is configured
http://django.readthedocs.io/en/latest/releases/1.7.html#standalone-scripts
I would also recommend jinja2. There is a nice article on django vs. jinja2 that gives some in-detail information on why you should prefere the later.
According to the Jinja documentation, Python 3 support is still experimental. So if you are on Python 3 and performance is not an issue, you can use django's built in template engine.
Django 1.8 introduced support for multiple template engines which requires a change to the way templates are initialized. You have to explicitly configure settings.DEBUG which is used by the default template engine provided by django. Here's the code to use templates without using the rest of django.
from django.template import Template, Context
from django.template.engine import Engine
from django.conf import settings
settings.configure(DEBUG=False)
template_string = "Hello {{ name }}"
template = Template(template_string, engine=Engine())
context = Context({"name": "world"})
output = template.render(context) #"hello world"
Thanks for the help folks. Here is one more addition. The case where you need to use custom template tags.
Let's say you have this important template tag in the module 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 to all 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 would be
{stackoverflow.com rox}
I would say Jinja as well. It is definitely more powerful than Django Templating Engine and it is stand alone.
If this was an external plug to an existing Django application, you could create a custom command and use the templating engine within your projects environment. Like this;
manage.py generatereports --format=html
But I don't think it is worth just using the Django Templating Engine instead of Jinja.
Found this:
http://snippets.dzone.com/posts/show/3339
Don't. Use StringTemplate instead--there is no reason to consider any other template engine once you know about it.
I echo the above statements. Jinja 2 is a pretty good superset of Django templates for general use. I think they're working on making the Django templates a little less coupled to the settings.py, but Jinja should do well for you.
While running the manage.py shell:
>>> from django import template
>>> t = template.Template('My name is {{ me }}.')
>>> c = template.Context({'me': 'ShuJi'})
>>> t.render(c)
Google AppEngine uses the Django templating engine, have you taken a look at how they do it? You could possibly just use that.