Jinja: Error confuso con Python 3 y plantillas que usan iteritems ()

Creado en 27 sept. 2012  ·  5Comentarios  ·  Fuente: pallets/jinja

Considerar:

#!/usr/bin/env python3

from collections import OrderedDict

import jinja2

t = '''
{% for key, value in d.iteritems() %}
* {{ key }}: {{ value }}
{% endfor %}
'''

jt = jinja2.Template(t)

d = OrderedDict()
d['one'] = 1
d['two'] = 2
d['three'] = 3

print(jt.render(d=d))

Cuando se ejecuta con Python 3, obtiene una excepción confusa:

Traceback (most recent call last):
  File "jinja2-OrderedDict.py", line 20, in <module>
    print(jt.render(d=d))
  File "/usr/lib/python3/dist-packages/jinja2/environment.py", line 895, in render
    return self.environment.handle_exception(exc_info, True)
  File "/usr/lib/python3/dist-packages/jinja2/environment.py", line 671, in handle_exception
    raise exc_value.with_traceback(tb)
  File "<template>", line 2, in <module>
jinja2.exceptions.UndefinedError: b"'collections.OrderedDict object' has no attribute 'iteritems'"

Esto se debe a que la plantilla usa iteritems, que se elimina en Python 3. De la excepción anterior, no está claro que el problema esté en la plantilla; debería estarlo.

Funciona para diccionarios Python 3 normales porque las líneas 205-210 de Jinja2 v2.61 agregan un método iteritems:

    # not available on python 3
    if hasattr(dict, 'iterkeys'):
        iterkeys = _all('iterkeys')
        itervalues = _all('itervalues')
        iteritems = _all('iteritems')
    del _all

¿Cuál es la mejor forma de solucionar este problema? ¿Detectar mejor objetos similares a dict, intentar escupir un error mejor, etc.?

Comentario más útil

Los diccionarios no tienen métodos de iteritem en 3.x. Deberá cambiar a .items() . No puedo hacer nada al respecto.

Todos 5 comentarios

Los diccionarios no tienen métodos de iteritem en 3.x. Deberá cambiar a .items() . No puedo hacer nada al respecto.

Sería bueno si hubiera un filtro incorporado para esta y otras rarezas de Python 2to3.

A menos que tenga grandes dictados, usar .items() no es / eso / malo

He aquí una forma de evitarlo:

importar seis

env = jinja2.Environment(loader=jinja2.FileSystemLoader('your_dir'))
env.globals['six_iteritems'] = six.iteritems
template = env.get_template('your_template')

Luego en tu plantilla:

usar:
{% para clave, valor en six_iteritems (su var)%}

Es un poco feo, pero funciona.

usando .items () en lugar .iteritems () funcionó

¿Fue útil esta página
0 / 5 - 0 calificaciones