python - for - jinja2 dump
Llamar a una función de pitón desde jinja2 (11)
Estoy usando jinja2, y quiero llamar a una función de python como ayudante, usando una sintaxis similar, como si estuviera llamando a una macro. jinja2 parece decidido a evitar que haga una llamada a función e insiste en que me repita copiando la función en una plantilla como una macro.
¿Hay alguna manera directa de hacer esto? Y, ¿hay alguna manera de importar un conjunto completo de funciones de python y tenerlas accesibles desde jinja2, sin pasar por un montón de rigamarole (como escribir una extensión)?
¿Hay alguna forma de importar un conjunto completo de funciones de Python y tenerlas accesibles desde jinja2?
Sí, hay, además de las otras respuestas anteriores, esto funciona para mí.
Crear una clase y llenarla con los métodos asociados, por ejemplo
class Test_jinja_object:
def __init__(self):
self.myvar = ''sample_var''
def clever_function (self):
return ''hello''
Luego, cree una instancia de su clase en su función de vista y pase el objeto resultante a su plantilla como un parámetro para la función render_template
my_obj = Test_jinja_object()
Ahora en tu plantilla, puedes llamar a los métodos de clase en jinja como tal
{{ my_obj.clever_function () }}
Creo que jinja deliberadamente hace que sea difícil ejecutar python ''arbitrario'' dentro de una plantilla. Intenta forzar la opinión de que menos lógica en las plantillas es algo bueno.
Puede manipular el espacio de nombres global dentro de una instancia de Environment
para agregar referencias a sus funciones. Debe hacerse antes de cargar cualquier plantilla. Por ejemplo:
from jinja2 import Environment, FileSystemLoader
def clever_function(a, b):
return u''''.join([b, a])
env = Environment(loader=FileSystemLoader(''/path/to/templates''))
env.globals[''clever_function''] = clever_function
Me gusta la respuesta de @ AJP . Lo usé textualmente hasta que terminé con muchas funciones. Luego cambié a un decorador de funciones de Python .
from jinja2 import Template
template = ''''''
Hi, my name is {{ custom_function1(first_name) }}
My name is {{ custom_function2(first_name) }}
My name is {{ custom_function3(first_name) }}
''''''
jinga_html_template = Template(template)
def template_function(func):
jinga_html_template.globals[func.__name__] = func
return func
@template_function
def custom_function1(a):
return a.replace(''o'', ''ay'')
@template_function
def custom_function2(a):
return a.replace(''o'', ''ill'')
@template_function
def custom_function3(a):
return ''Slim Shady''
fields = {''first_name'': ''Jo''}
print(jinga_html_template.render(**fields))
¡Las funciones buenas tienen un __name__
!
Nunca vi una forma tan simple en los documentos oficiales o en el desbordamiento de la pila, pero me sorprendió cuando encontré esto:
# jinja2.__version__ == 2.8
from jinja2 import Template
def calcName(n, i):
return '' ''.join([n] * i)
template = Template("Hello {{ calcName(''Gandalf'', 2) }}")
template.render(calcName=calcName)
# or
template.render({''calcName'': calcName})
Para importar todas las funciones integradas, puede usar:
app.jinja_env.globals.update(__builtins__)
Agregue .__dict__
después de __builtins__
si esto no funciona.
Basado en la respuesta de John32323 .
Para llamar a una función python desde Jinja2, puede usar filtros personalizados que funcionan de forma similar a los globales: http://jinja.pocoo.org/docs/dev/api/#writing-filters
Es bastante simple y útil. En un archivo myTemplate.txt, escribí:
{{ data|pythonFct }}
Y en una secuencia de comandos python:
import jinja2
def pythonFct(data):
return "This is my data: {0}".format(data)
input="my custom filter works!"
loader = jinja2.FileSystemLoader(path or ''./'')
env = jinja2.Environment(loader=loader)
env.filters[''pythonFct''] = pythonFct
result = env.get_template("myTemplate.txt").render(data=input)
print(result)
Si lo está haciendo con Django, puede pasar la función con el contexto:
context = {
''title'':''My title'',
''str'': str,
}
...
return render(request, ''index.html'', context)
Ahora podrá usar la función str
en la plantilla jinja2
Usa una lambda para conectar la plantilla a tu código principal
return render_template("clever_template", clever_function=lambda x: clever_function x)
Entonces puede llamar sin problemas a la función en la plantilla
{{clever_function(value)}}
Nota: ¡Esto es específico de Flask!
Sé que esta publicación es bastante antigua, pero hay mejores métodos para hacerlo en las versiones más nuevas de Flask utilizando procesadores de contexto.
Las variables se pueden crear fácilmente:
@app.context_processor
def example():
return dict(myexample=''This is an example'')
Lo anterior se puede usar en una plantilla Jinja2 con Flask así:
{{ myexample }}
(Qué salidas This is an example
)
Además de las funciones completas:
@app.context_processor
def utility_processor():
def format_price(amount, currency=u''€''):
return u''{0:.2f}{1}''.format(amount, currency)
return dict(format_price=format_price)
Lo anterior cuando se usa así:
{{ format_price(0.33) }}
(Que genera el precio de entrada con el símbolo de moneda)
Alternativamente, puedes usar filtros jinja , horneados en Flask. Ej. Usando decoradores:
@app.template_filter(''reverse'')
def reverse_filter(s):
return s[::-1]
O bien, sin decoradores, y registrando manualmente la función:
def reverse_filter(s):
return s[::-1]
app.jinja_env.filters[''reverse''] = reverse_filter
Los filtros aplicados con los dos métodos anteriores se pueden usar así:
{% for x in mylist | reverse %}
{% endfor %}
Para aquellos que usan Flask, pon esto en tu __init__.py
:
def clever_function():
return u''HELLO''
app.jinja_env.globals.update(clever_function=clever_function)
y en su plantilla, {{ clever_function() }}
con {{ clever_function() }}
from jinja2 import Template
def custom_function(a):
return a.replace(''o'', ''ay'')
template = ''Hey, my name is {{ custom_function(first_name) }}''
jinga_html_template = Template(template)
jinga_html_template.globals[''custom_function''] = custom_function
fields = {''first_name'': ''Jo''}
print jinga_html_template.render(**fields)
Se producirá:
Hey, my name is Jay
Funciona con Jinja2 versión 2.7.3