【问题标题】:why is django using ascii instead of utf-8?为什么 django 使用 ascii 而不是 utf-8?
【发布时间】:2016-07-23 05:33:15
【问题描述】:

在我的 sqlite3 数据库中以管理员身份添加数据(非 ascii 字符)时,出现以下错误:

Exception Type: UnicodeEncodeError at /admin/Project/vin/add/
Exception Value: 'ascii' codec can't encode character u'\xe2' in position 2:        
ordinal not in range(128)

我真的不知道出了什么问题,因为它在所有不同的设置中都是用 utf-8 编写的......而且 ascii 只出现在错误中。

我得到了解释

Django Version: 1.9.4
Python Version: 2.7.10
Installed Applications:
['django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'Project']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware']



> Traceback:

> File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-pac
> kages/django/core/handlers/base.py" in get_response
>   149.                     response = self.process_exception_by_middleware(e, request)
> 
> File
> "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/django/core/handlers/base.py"
> in get_response
>   147.                     response = wrapped_callback(request, *callback_args, **callback_kwargs)
> 
> File
> "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/django/contrib/admin/options.py"
> in wrapper
>   541.                 return self.admin_site.admin_view(view)(*args, **kwargs)
> 
> File
> "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/django/utils/decorators.py"
> in _wrapped_view
>   149.                     response = view_func(request, *args, **kwargs)
> 
> File
> "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/django/views/decorators/cache.py"
> in _wrapped_view_func
>   57.         response = view_func(request, *args, **kwargs)
> 
> File
> "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/django/contrib/admin/sites.py"
> in inner
>   244.             return view(request, *args, **kwargs)
> 
> File
> "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/django/contrib/admin/options.py"
> in add_view
>   1437.         return self.changeform_view(request, None, form_url, extra_context)
> 
> File
> "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/django/utils/decorators.py"
> in _wrapper
>   67.             return bound_func(*args, **kwargs)
> 
> File
> "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/django/utils/decorators.py"
> in _wrapped_view
>   149.                     response = view_func(request, *args, **kwargs)
> 
> File
> "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/django/utils/decorators.py"
> in bound_func
>   63.                 return func.__get__(self, type(self))(*args2, **kwargs2)
> 
> File
> "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/django/utils/decorators.py"
> in inner
>   184.                     return func(*args, **kwargs)
> 
> File
> "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/django/contrib/admin/options.py"
> in changeform_view
>   1382.                     self.log_addition(request, new_object, change_message)
> 
> File
> "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/django/contrib/admin/options.py"
> in log_addition
>   714.             object_repr=force_text(object),
> 
> File
> "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/django/utils/encoding.py"
> in force_text
>   80.                 s = six.text_type(bytes(s), encoding, errors)

vin 模型

class Vin (models.Model):
    nom_vin =models.CharField (max_length = 20)
    millesime = models.IntegerField() 
    quantity = models.FloatField()
    appelation = models.ForeignKey(Appelation)
    def __str__(self):
        return self.nom_vin

【问题讨论】:

  • 你确定你使用的是 Python 2.7.10 吗?回溯说 3.5…
  • 也许你正在打印到终端并且终端有ascii编码?
  • 克里斯我不知道为什么它说 2.7.10 因为在创建我为 python 3.5 选择的项目时,回溯说同样的......这可能是错误的根源吗?跨度>
  • @Reygrip,你问题中的 2.7.10 文本来自哪里?您是否在项目的某个地方看到了这一点?
  • @Chris 是的,它是从恢复错误...我不知道为什么

标签: python django utf-8 ascii


【解决方案1】:

试试:

class Vin (models.Model):
    nom_vin =models.CharField (max_length = 20)
    millesime = models.IntegerField() 
    quantity = models.FloatField()
    appelation = models.ForeignKey(Appelation)
    def __unicode__(self):                        #You have __str__
        return self.nom_vin

【讨论】:

  • 这肯定只适用于 Python 2.x 吗?你能进一步解释一下吗?
【解决方案2】:

我几乎没有接近理解 Python 中的编码繁琐,但在尝试解码这个错误时,我离它更近了一点。如果您只想要正确的解决方案,请跳到最后(提示:python_2_unicode_compatible)。

根据Porting to Python 3,在 Python 2 中,您可以同时拥有 __str__()(它必须返回一个字节字符串/对象(类型 'str'))和 __unicode__()(它返回一个'unicode' 一);但如果你只有其中一个就足够了:

print 语句和 str 内置调用 __str__() 以确定对象的人类可读表示。 unicode 内置调用 __unicode__() 如果它存在,否则回退到 __str__() 并使用系统编码解码结果。相反,Model 基类通过编码为 UTF-8 自动从 __unicode__() 派生 __str__()。

另一方面,Python 3 将 unicode 作为文本的默认值,并且只需要 __str__(),提供一个 unicode 字符串,类型为“str”(是的,与 P2 的字节字符串同名)。 Weeeeeell,还有 __bytes__(),但你可能永远不需要它。

这一切都很好,花花公子,直到出现 encoding.py 及其管理界面使用的 force_text 方法:

def force_text(s, encoding='utf-8', strings_only=False, errors='strict'):
"""
Returns a text object representing 's' -- unicode on Python 2 and str on
Python 3. Treats bytestrings using the 'encoding' codec.
"""
[...]
try:
        if not issubclass(type(s), six.string_types):
            if six.PY3:
                if isinstance(s, bytes):
                    s = six.text_type(s, encoding, errors)
                else:
                    s = six.text_type(s)
            elif hasattr(s, '__unicode__'):
                s = six.text_type(s)
            else:
                s = six.text_type(bytes(s), encoding, errors)

错误在最后一行,我们只能用 Python 2 触发它(因为 Python 3 会触发 if six.PY3),当没有 __unicode__ 方法时,我们正在使用 unicode_literals(encoding.py 可以) ,所以bytes()(这只是str()的别名)在需要一个字节时传递了一个unicode对象:

 $ python2
Python 2.7.11+ (default, Mar 30 2016, 21:00:42) 
# Python 2 uses bytes (type "str")  strings by default:
>>> bstr = 'â'
>>> type(bstr)
<type 'str'>
>>> bstr
'\xc3\xa2'
>>> bytes(bstr)
'\xc3\xa2'

# unicode_literals changes the default to unicode strings:
>>> from __future__ import unicode_literals
>>> ustr = 'â'
>>> type(ustr)
<type 'unicode'>
>>> ustr
u'\xe2'
# bytes() (str(), actually) expects a byte string, not unicode:
>>> bytes(ustr)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe2' in position 0: ordinal not in range(128) '
# We can encode ustr to bytes like so:
>>> bytes(ustr.encode('utf-8'))
'\xc3\xa2'
# Or with the equivalent b operator, for literals:
>>> bytes(b'â')
'\xc3\xa2'

# bstr has not changed:
>>> bytes(bstr)
'\xc3\xa2'

为了完整起见,Python 3 的默认文字类型为 unicode,但也称其为“str”(字节字符串为“bytes”):

$ python3
Python 3.5.1+ (default, Jan 13 2016, 15:09:18) 
>>> ustr='á'
>>> ustr
'á'
>>> type(ustr)
<class 'str'>

>>> bstr='á'.encode('utf-8')
>>> bstr
b'\xc3\xa1'
>>> type(bstr)
<class 'bytes'>

# Note that you can't use `b` to enconde a non-ascii literal     
>>> bstr=b'á'
  File "<stdin>", line 1
SyntaxError: bytes can only contain ASCII literal characters.

现在,您似乎正在运行 Python 2.7,但使用的是 3.5 库!不知道你是怎么做到的,但是按照 Volodymyr 的建议,你已经使你的代码与 Python 2 兼容,但与需要 __str__() 的 Python 3 不兼容。

定义 __str__ 和 __unicode__ 以返回 self.name 以它被转换的任何类型似乎对两者都有效,但它一定会在某个时候中断,就像你发生的那样,因为人们不会费心检查字符串类型(即让我有点困惑)。你可以有一个 __str__ 来检查 Python 版本和字符串类型,并相应地传递或编码值,但 Django 家伙已经处理好了:

Django 适配的 Python 2 和 3 兼容库——Six(那是 2*3,明白吗?)——提供了一个类装饰器 python_2_unicode_compatible

将 __str__ 方法别名为 __unicode__ 并创建一个新的 __str__ 返回使用 UTF-8 编码的 __unicode__() 的结果的方法。

这在本教程的第 2 部分中使用(docs.djangoproject.com/en/1.9/intro/tutorial02/#playing-with-the-api — 抱歉,无法创建更多链接):

from django.db import models
from django.utils.encoding import python_2_unicode_compatible

@python_2_unicode_compatible  # only if you need to support Python 2
class Question(models.Model):
    # ...
    def __str__(self):
        return self.question_text

呸。有了这一切,还有 Ned Batchelder 的 Pragmatic Unicode (nedbatchelder.com/text/unipain.html),我想我开始掌握它了。不过,我可能会坚持使用 Python 3... 或 PHP... ^_^

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-05-10
    • 2013-03-04
    • 2011-12-13
    • 2016-04-04
    • 1970-01-01
    • 2016-09-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多