web-dev-qa-db-fra.com

Utilisation de caractères utf-8 dans un modèle Jinja2

J'essaie d'utiliser des caractères utf-8 lors du rendu d'un modèle avec Jinja2. Voici à quoi ressemble mon modèle:

<!DOCTYPE HTML>
<html manifest="" lang="en-US">
<head>
    <meta charset="UTF-8">
    <title>{{title}}</title>
...

La variable de titre est définie quelque chose comme ceci:

index_variables = {'title':''}
index_variables['title'] = myvar.encode("utf8")

template = env.get_template('index.html')
index_file = open(preview_root + "/" + "index.html", "w")

index_file.write(
    template.render(index_variables)
)
index_file.close()

Maintenant, le problème est que myvar est un message lu dans une file de messages et peut contenir ces caractères spéciaux utf8 (ex. "Séptimo Cine"). 

Le modèle rendu ressemble à quelque chose comme:

...
    <title>S\u00e9ptimo Cine</title>
...

et je veux que ce soit:

...
    <title>Séptimo Cine</title>
...

J'ai fait plusieurs tests mais je ne peux pas le faire fonctionner.

  • J'ai essayé de définir la variable de titre sans .encode ("utf8") , mais une exception est générée (ValueError: un objet octet, et non un objet). le message initial est unicode

  • J'ai utilisé chardet.detect pour obtenir l'encodage du message (c'est "ascii"), puis j'ai fait ceci: myvar.decode ("ascii"). Encode ("cp852"), mais le titre est toujours pas rendu correctement.

  • Je me suis également assuré que mon modèle était un fichier UTF-8, mais cela ne faisait aucune différence.

Auriez vous des idées pour faire ça?

29
alex.ac

TL; DR:

  • Passer Unicode à template.render()
  • Encodez le résultat unicode rendu dans une chaîne d'octets avant de l'écrire dans un fichier

Cela m'a laissé perplexe pendant un moment. Parce que tu fais 

index_file.write(
    template.render(index_variables)
)

dans une déclaration, il s’agit essentiellement d’une ligne en ce qui concerne Python; le traçage que vous obtenez est donc trompeur: l’exception que j’ai eue lors de la recréation de votre scénario de test ne s’est pas produite dans template.render(index_variables), mais dans index_file.write(). Donc, diviser le code comme ça

output = template.render(index_variables)
index_file.write(output)

était la première étape pour diagnostiquer où exactement la UnicodeEncodeError se produit.

Jinja renvoie unicode en laissant le rendu du modèle. Par conséquent, vous devez encoder le résultat dans une chaîne d'octets avant de pouvoir l'écrire dans un fichier:

index_file.write(output.encode('utf-8'))

La deuxième erreur est que vous passez une chaîne d'octets codée utf-8 à template.render() - Jinja veut unicode . Donc, en supposant que votre myvar contient du UTF-8, vous devez d’abord le décoder en Unicode:

index_variables['title'] = myvar.decode('utf-8')

Donc, pour tout mettre ensemble, cela fonctionne pour moi:

# -*- coding: utf-8 -*-

from jinja2 import Environment, PackageLoader
env = Environment(loader=PackageLoader('myproject', 'templates'))


# Make sure we start with an utf-8 encoded bytestring
myvar = 'Séptimo Cine'

index_variables = {'title':''}

# Decode the UTF-8 string to get unicode
index_variables['title'] = myvar.decode('utf-8')

template = env.get_template('index.html')

with open("index_file.html", "w") as index_file:
    output = template.render(index_variables)

    # jinja returns unicode - so `output` needs to be encoded to a bytestring
    # before writing it to a file
    index_file.write(output.encode('utf-8'))
31
Lukas Graf

Essayez de changer votre commande de rendu en ceci ...

template.render(index_variables).encode( "utf-8" )

La documentation de Jinja2 indique "Cela renverra le modèle rendu sous forme de chaîne unicode."

http://jinja.pocoo.org/docs/api/?highlight=render#jinja2.Template.render

J'espère que cela t'aides!

5
Andrew Kloos

Et si rien ne fonctionne parce que vous avez un mélange de langues, comme dans mon cas, remplacez simplement "utf-8" par "utf-16"

Toutes les options d'encodage ici:

https://docs.python.org/2.4/lib/standard-encodings.html

0
alfonso olivas