【问题标题】:django countries encoding is not giving correct namedjango国家编码没有给出正确的名称
【发布时间】:2015-08-18 17:07:57
【问题描述】:

我在国家列表中使用django_countries 模块,问题是有几个国家有特殊字符,如'Åland Islands''Saint Barthélemy'

我正在调用这个方法来获取国家名称:

country_label = fields.Country(form.cleaned_data.get('country')[0:2]).name

我知道 country_label 是 django utils 的惰性翻译代理对象,但它没有给出正确的名称,而是给出了'Ã…land Islands'。请问有什么建议吗?

【问题讨论】:

    标签: python django python-unicode django-countries


    【解决方案1】:

    Django 使用代码点存储unicode 字符串,并将字符串标识为 unicode 以供进一步处理。 UTF-8 使用四个 8 位字节编码,因此 Django 使用的 unicode 字符串需要在某些时候从代码点表示法解码或解释为其 UTF-8 表示法。 在奥兰群岛的情况下,似乎正在发生的事情是它采用 UTF-8 字节编码并将其解释为代码点来转换字符串。

    django_countries 返回的字符串很可能是u'\xc5land Islands',其中\xc5 是Å 的UTF 代码点符号。在 UTF-8 字节表示法中,\xc5 变为 \xc3\x85,其中每个数字 \xc3\x85 是一个 8 位字节。看: http://www.ltg.ed.ac.uk/~richard/utf-8.cgi?input=xc5&mode=hex

    或者您可以使用 country_label = fields.Country(form.cleaned_data.get('country')[0:2]).name.encode('utf-8') 从 u'\xc5land Islands' 转到 '\xc3\x85land Islands'

    如果您将每个字节用作代码点,您会看到它会为您提供以下字符:Ã… 见:http://www.ltg.ed.ac.uk/~richard/utf-8.cgi?input=xc3&mode=hex 还有:http://www.ltg.ed.ac.uk/~richard/utf-8.cgi?input=x85&mode=hex

    查看带有这些字符的 html 符号的代码 sn-p。

    <div id="test">Ã…Å</div>

    所以我猜你的应用程序中有 2 种不同的编码。从u'\xc5land Islands'u'\xc3\x85land Islands' 的一种方法是在utf-8 环境中编码为UTF-8,它将u'\xc5' 转换为'\xc3\x85',然后从iso-8859 解码为unicode,这将给出u'\xc3\x85land Islands'。但由于它不在您提供的代码中,我猜它发生在您设置 country_label 和您的输出未正确显示之间的某处。由于编码设置而自动进行,或者通过某处的显式分配。

    首次编辑

    要为您的应用设置编码,请在 py 文件顶部添加 # -*- coding: utf-8 -*- 并在模板中添加 <meta charset="UTF-8">。 要从 django.utils.functional.proxy 对象中获取 unicode 字符串,您可以调用 unicode()。像这样:

    country_label = unicode(fields.Country(form.cleaned_data.get('country')[0:2]).name)
    

    第二次编辑

    找出问题所在的另一种方法是使用force_bytes (https://docs.djangoproject.com/en/1.8/ref/utils/#module-django.utils.encoding) 像这样:

    from django.utils.encoding import force_bytes
    country_label = fields.Country(form.cleaned_data.get('country')[0:2]).name
    forced_country_label = force_bytes(country_label, encoding='utf-8', strings_only=False, errors='strict') 
    

    但是由于您已经尝试了许多转换但都没有成功,所以问题可能更复杂。你能分享你的django_countriesPython 版本和你的 django 应用程序语言设置吗? 你还可以直接在你的djano_countries 包中查看(应该在你的python 目录中),找到文件data.py 并打开它看看它的样子。可能数据本身已损坏。

    【讨论】:

    • 我在代码中使用了country_label = fields.Country(form.cleaned_data.get('country')[0:2]).name.encode('utf-8'),但它仍然呈现为Ã…land。我正在使用渲染方法来获取模板。
    • 查看编辑,我想 country_label 直接进入上下文并且在渲染之前没有保存在数据库中?
    • @mad_programmer 如果将编码参数传递给unicode() 会发生什么情况,如下所示:unicode(fields.Country(...).name, 'UTF-8')
    • @xyres 你的解决方案给出了错误TypeError: coercing to Unicode: need string or buffer, __proxy__ found
    • @JulienGrégoire 不,您建议的解决方案不起作用,它仍然给出相同的字符串。是的,它通过渲染方法进入上下文,我直接在模板中使用它。不会存储在 db 中的任何位置。
    【解决方案2】:

    就在这周,我遇到了类似的编码错误。我认为问题在于机器编码与 Python 上的不同。尝试将此添加到您的.bashrc.zshrc

    export LC_ALL=en_US.UTF-8
    export LANG=en_US.UTF-8
    

    然后,打开一个新终端并再次运行 Django 应用程序。

    【讨论】:

      【解决方案3】:

      尝试:

      from __future__ import unicode_literals #Place as first import.
      

      与/或

      country_label = fields.Country(form.cleaned_data.get('country')[0:2]).name.encode('latin1').decode('utf8')
      

      【讨论】:

      • 这两种解决方案都不起作用。第二个给出例外。在第二个选项中,我得到 UnicodeDecodeError UnicodeDecodeError: 'utf8' codec can't decode byte 0xc5 in position 0: invalid continuation byte
      猜你喜欢
      • 2012-01-24
      • 1970-01-01
      • 2018-02-22
      • 2014-01-10
      • 2016-06-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-12
      相关资源
      最近更新 更多