在Jinja2模板中使用utf-8字符

ale*_*.ac 30 python utf-8 character-encoding jinja2 python-2.7

我在使用Jinja2渲染模板时尝试使用utf-8字符.以下是我的模板的样子:

<!DOCTYPE HTML>
<html manifest="" lang="en-US">
<head>
    <meta charset="UTF-8">
    <title>{{title}}</title>
...
Run Code Online (Sandbox Code Playgroud)

标题变量设置如下:

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()
Run Code Online (Sandbox Code Playgroud)

现在,问题是myvar是从消息队列中读取的消息,可以包含那些特殊的utf8字符(例如"SéptimoCine").

渲染的模板看起来像:

...
    <title>S\u00e9ptimo Cine</title>
...
Run Code Online (Sandbox Code Playgroud)

我希望它是:

...
    <title>Séptimo Cine</title>
...
Run Code Online (Sandbox Code Playgroud)

我已经做了几次测试,但我不能让它工作.

  • 我试图设置title变量而没有.encode("utf8"),但它抛出异常(ValueError:期望一个字节对象,而不是unicode对象),所以我的猜测是初始消息是unicode

  • 我使用chardet.detect来获取消息的编码(它是"ascii"),然后执行以下操作:myvar.decode("ascii").encode("cp852"),但标题仍未正确呈现.

  • 我还确保我的模板是UTF-8文件,但它没有什么区别.

关于如何做到这一点的任何想法?

Luk*_*raf 34

TL; DR:

  • 将Unicode传递template.render()
  • 在将呈现的unicode结果写入文件之前,将其编码为字节串

这让我困惑了一段时间.因为你这样做

index_file.write(
    template.render(index_variables)
)
Run Code Online (Sandbox Code Playgroud)

在一个声明中,这基本上只是Python所关注的一行,所以你得到的回溯是误导性的:我在重新创建测试用例时遇到的异常没有发生template.render(index_variables),而是发生了index_file.write().所以像这样拆分代码

output = template.render(index_variables)
index_file.write(output)
Run Code Online (Sandbox Code Playgroud)

是诊断确切UnicodeEncodeError发生的第一步.

当你让它渲染模板时,Jinja会返回unicode.因此,您需要先将结果编码为bytestring,然后才能将其写入文件:

index_file.write(output.encode('utf-8'))
Run Code Online (Sandbox Code Playgroud)

第二个错误是你传入一个utf-8编码的字节串template.render()- Jinja想要unicode.因此,假设您myvar包含UTF-8,则需要先将其解码为unicode:

index_variables['title'] = myvar.decode('utf-8')
Run Code Online (Sandbox Code Playgroud)

所以,总而言之,这对我有用:

# -*- 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'))
Run Code Online (Sandbox Code Playgroud)


And*_*oos 6

尝试将渲染命令更改为此...

template.render(index_variables).encode( "utf-8" )
Run Code Online (Sandbox Code Playgroud)

Jinja2的文档说"这将把渲染的模板作为unicode字符串返回."

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

希望这可以帮助!