web-dev-qa-db-ja.com

Jinja2テンプレートでutf-8文字を使用する

Jinja2でテンプレートをレンダリングするときにutf-8文字を使用しようとしています。テンプレートは次のようになります。

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

タイトル変数は次のように設定されます。

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()

現在、問題はmyvarがメッセージキューから読み取られたメッセージであり、これらの特別なutf8文字(例: "SéptimoCine")を含むことができるということです。

レンダリングされたテンプレートは次のようになります。

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

そして私はそれが欲しいです:

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

私はいくつかのテストを行いましたが、これを機能させることはできません。

  • 。encode( "utf8")なしでタイトル変数を設定しようとしましたが、例外をスローします(ValueError:ユニコードオブジェクトではなく、バイトオブジェクトが必要です。 )、したがって、私の推測では、最初のメッセージはユニコードである

  • chardet.detectを使用してメッセージのエンコードを取得し(「ascii」)、次に以下を実行しました。myvar.decode( "ascii")。encode( "cp852")ですが、タイトルはまだ正しくレンダリングされません。

  • また、テンプレートがUTF-8ファイルであることも確認しましたが、違いはありませんでした。

これを行う方法に関するアイデアはありますか?

29
alex.ac

TL; DR:

  • Unicodetemplate.render()に渡す
  • レンダリングされたユニコード結果をバイトストリングにエンコードしてからファイルに書き込みます

これは私をしばらく困惑させました。あなたがするから

index_file.write(
    template.render(index_variables)
)

1つのステートメントでは、これは基本的にPythonが関係する1行だけなので、トレースバックは誤解を招く可能性があります。テストケースの再作成時に得た例外はtemplate.render(index_variables)が、代わりにindex_file.write()にあるので、このようにコードを分割します

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

UnicodeEncodeErrorが正確に発生する場所を診断する最初のステップでした。

Jinjaは、テンプレートをレンダリングできるようにするユニコードを返します。したがって、ファイルに書き込む前に、結果をバイト文字列にエンコードする必要があります。

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

2番目のエラーは、utf-8エンコードされたバイト文字列をtemplate.render()に渡すことです- Jinjaはunicode を必要とします。したがって、myvarにUTF-8が含まれていると仮定すると、最初にUnicodeにデコードする必要があります。

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

それで、それをすべてまとめると、これは私にとってうまくいきます:

# -*- 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'))
33
Lukas Graf

レンダーコマンドをこれに変更してみてください...

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

Jinja2のドキュメントには、「これにより、レンダリングされたテンプレートがUnicode文字列として返されます」と書かれています。

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

お役に立てれば!

5
Andrew Kloos

そして、私の場合のように、言語が混在しているために何も機能しない場合は、「utf-8」を「utf-16」に置き換えてください。

ここにあるすべてのエンコードオプション:

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

0
alfonso olivas