How do you pass an array to a mako template? - python

I want to pass an array of strings to Mako's render method but this doesn't work:
from mako.template import Template
mytemplate = Template(filename="some.template")
str = mytemplate.render(first="John", last="Smith", nicknames=[
"JJ", "Johnny", "Jon"])
print(str)
some.template =
Hello ${first} ${last}
Your nicknames are:
% for n in ${nicknames}:
${n}
% endfor

Within a '%' line, you're writing regular Python code that doesn't need the escaping:
% for n in nicknames:
${n}
% endfor

Related

how to format large numbers using spaces instead fo comma?

I am using django.contrib.humanize intcomma tag to format large numbers like this $18,162,711,641
but what I want spaces instead of comma, like this $18 162 711 641
How can I achieve this? Thank you.
Thanks to Abdul Niyas P M
This is what works for me. I had to put this in app_name/templatetags directory and load it in template using {% load intspace %}
from django import template
register = template.Library()
#register.filter
def intspace(value):
import re
orig = str(value)
new = re.sub(r"^(-?\d+)(\d{3})", r"\g<1> \g<2>", orig)
if orig == new:
return new
else:
return intspace(new)
inside template you can use it like
{{ 18162711641|intspace }}

Creating strings with jinja structure inside

I'm trying to generate django code, however when trying to create the templates,
classname = 'person'
content = "{% trans 'Add' %}\n" % classname
I get the following error:
TypeError: %u format: a number is required, not unicode
Python tries to evaluate the "{% u" and I get that error.
I tried also with "format" but error stays.
You can double encode jinja's % characters:
content = "{%% trans 'Add' %%}\n" % classname
or double encode Jinjas {} characters and use format():
content = "{{% trans 'Add' %}}\n".format(classname=classname)
Or simply split your template into three parts:
content = "<a href='{% url 'core.views.add_"
content += '%s' % classname
cotnent += " %}' class=\"btn btn-default\">{% trans 'Add' %}</a>\n"
You can do simple string concatenation in this case:
content = "{% trans 'Add' %}\n"
Example:
>>> classname = 'person'
>>> content = "{% trans 'Add' %}\n"
>>> content
>>> '{% trans \'Add\' %}\n'
If you want a literal % in your string, use two percent signs %%:
"{%% trans 'Add' %%}\n" % classname
If you use the format() method, you need to use {{ and }}:
"{{% trans 'Add' %}}\n".format(classname)

What's the most Pythonic/Django-y way to store long string assets?

I have a function in my Django app that has a dictionary containing several long strings. When that function is called, those strings are formatted and the dictionary returned.
For example:
def my_strings(foo, bar, baz):
return = {
'string1': 'a really long string! %s' % foo,
'string2': 'another long one. %s %s' % (foo, bar),
'string3': 'yet another! %s %s %s' % (foo, bar, baz),
}
However, having all these long strings, stored in a Python file is ugly and it seems there should be a cleaner way to do it.
I'd toyed with putting them in a template file and doing some rendering, like so:
mytemplate.txt
{% if string1 %}
a really long string! {{ foo }}
{% endif %}
{% if string2 %}
another long one. {{ foo }} {{ bar }}
{% endif %}
{% if string3 %}
yet another! {{ foo }} {{ bar }} {{ baz }}
{% endif %}
Python
def my_strings(foo, bar, baz):
arg_dict = {
'foo': foo,
'bar': bar,
'baz': baz,
}
my_strings = {}
string_names = ['string1', 'string2', 'string3']
for s in string_names:
arg_dict[s] = True
my_strings[s] = render_to_string('mytemplate.txt', arg_dict).strip()
del arg_dict[s]
return my_strings
But that seems a little too roundabout, and most likely less performant.
Is there a preferred way in Python, or Django specifically, to handle storing and formatting long string assets?
Some extra context: the string assets are either HTML or plaintext. The dictionary is eventually iterated over and all instances of each key in yet another string are replaced with its string value.
I would treat this as something similar to the way many i8n compilation code does it.
Store the long strings in a dictionary in a separate file. Import that dictionary and then format the desired string in your code.
You could place the strings in a module like longstrings.py
STRING1 = ("Bla bla"
" more text"
" even more text")
STRING2 = ("Bla bla"
" more text"
" even more text")
and then
from longstrings import *
def my_strings(foo, bar, baz):
return = {
'string1': STRING1 % foo,
'string2': STRING2 % (foo, bar),
'string3': STRING2 % (foo, bar, baz),
}
You could also create a class for your long strings, and they would be stored in the DB. This would allow you to access them and modify them as any other object. For example, you could use the Django admin tool if you want to modify a specific string.

How to display string which contains django template variables?

Let's say I have an string variable called *magic_string* which value is set to "This product name is {{ product.name }}" and it's avaible at django template. Is it ever possible to parse that variable to show me "This product name is Samsung GT-8500" instead (assuming that name of the product is "GT-8500" and variable {{ product.name }} is avaible at the same template) ?
I was trying to do something like this, but it doesn't work (honestly ? Im not surprised):
{{ magic_string|safe }}
Any ideas/suggestions about my problem ?
Write custom template tag and render that variable as a template.
For example look at how "ssi" tag is written.
On the other hand, can you render this string in your view? Anyway here is an untested version of that tag:
#register.tag
def render_string(parser, token):
bits = token.contents.split()
if len(bits) != 2:
raise TemplateSyntaxError("...")
return RenderStringNode(bits[1])
class RenderStringNode(Node):
def __init__(self, varname):
self.varname = varname
def render(self, context):
var = context.get(self.varname, "")
return Template(var).render(context)
Perhaps I dont understand your question but what about,
from django.template import Context, Template
>>> t = Template("This product name is {{ product.name }}")
>>> c = Context({"product.name": " Samsung GT-8500"})
>>> t.render(c)
Regards.

Jinja2 compile extension after includes

In Jinja2, is it possible to have a Node from the AST render after all include statements have completed?
This is a key piece of a solution to a bigger puzzle.
Example code:
x.py
from jinja2 import nodes, Environment, FileSystemLoader
from jinja2.ext import Extension
class XExtension(Extension):
tags = set(['x', 'get_x'])
def __init__(self, environment):
super(XExtension, self).__init__(environment)
environment.extend(
x = 0,
)
def parse(self, parser):
tag = parser.stream.next()
return getattr(self, "_%s" % str(tag))(parser, tag)
def _get_x(self, parser, tag):
""" Return the output """
return nodes.Const(self.environment.x)
def _x(self, parser, tag):
""" Add an x """
self.environment.x += 1
return nodes.Const('<!-- Adding an X -->')
env = Environment(
loader = FileSystemLoader('.'),
extensions = [XExtension],
)
template = env.get_template('x.html')
print template.render()
x.html
Xx {% x %} Xx {% x %}
{% include "y.html" %}
Xs xes: {% get_x %}
y.html
Yx {% x %}
Ys xes: {% get_x %}
The output is
Xx <!-- Adding an X --> Xx <!-- Adding an X -->
Yx <!-- Adding an X -->
Ys xes:3
Xs xes 2
How may it be possible to have Xs xes count the X's in y.html, which is the behaviour I desire and expect?
In other words, is there a way to delay the parsing or flattening to text returned from the _get_x() in x.html?
Thank you very much for reading.
Kind regards,
Brian
Jinja2 does streaming of template data. The template is evaluated instruction for instruction into a stream of smaller strings that gets concatenated into an actual unicode string by the render() method. However you can also get hold of the stream by calling into generate() instead of render().
With some in-band signalling and postprocessing of the stream one might probably be able to implement something like that, but it's against the way of how Jinja2 was designed so it might break horribly and is totally unsupported.

Categories

Resources