UnicodeEncodeError:'ascii'编解码器无法编码字符

时间:2010-09-15 08:24:35

标签: django file-upload django-admin nginx django-uploads

上传带有非ASCII字符的文件时,我得到UnicodeEncodeError:

Exception Type: UnicodeEncodeError at /admin/studio/newsitem/add/
Exception Value: 'ascii' codec can't encode character u'\xf8' in position 78: ordinal not in range(128)

请参阅full stack trace

我用MySQL和nginx以及FastCGI运行Django 1.2。

这是根据Django Trac database修复的问题,但我仍然遇到问题。欢迎任何有关如何解决的建议。

编辑:这是我的图片栏:

image = models.ImageField(_('image'), upload_to='uploads/images', max_length=100)

12 个答案:

答案 0 :(得分:39)

对于使用Supervisor运行Django时遇到此问题的任何人,解决方案是添加例如以下是Supervisor配置的supervisord部分:

environment=LANG="en_US.utf8", LC_ALL="en_US.UTF-8", LC_LANG="en_US.UTF-8"

这解决了在Debian Squeeze上运行Supervisor 3.0a8的问题。

答案 1 :(得分:24)

在必须在只接受ascii的地方(如控制台或路径)中显示unicode字符串的情况下,您必须告诉Python您希望它替换非ascii字符的最佳工作量。

>> problem_str = u'This is not all ascii\xf8 man'
>> safe_str = problem_str.encode('ascii', 'ignore')
>> safe_str
'This is not all ascii man'

管理员可以通过谨慎处理Django模板来防止编码问题,但是如果你曾经添加过自定义列而忘记将值转换为ascii,或者覆盖了 str 方法模型而忘记这样做,你会得到同样的错误,阻止模板渲染。

如果将此字符串保存到您的(希望是utf8)数据库中就没有问题,看起来您正在尝试上传使用具有非ascii字符的实体标题的文件。

答案 2 :(得分:12)

希望这会有所帮助。 就我而言,我正在通过daemontools运行django。

设置

export LANG='en_US.UTF-8'
export LC_ALL='en_US.UTF-8'
执行manage.py之前在运行脚本中的

解决了uploads filename

的问题

答案 3 :(得分:12)

在对此进行调查后,我发现我没有在主要的Nginx配置文件中设置charset:

http {
  charset  utf-8;
}

通过添加上述内容,问题就消失了,我认为这是处理此问题的正确方法。

答案 4 :(得分:10)

akaihola的回答很有帮助。对于那些通过upstart脚本管理uWSGI运行django app的人,只需将这些行添加到/etc/init/yourapp.conf

env LANG="en_US.utf8"
env LC_ALL="en_US.UTF-8"
env LC_LANG="en_US.UTF-8"

它解决了我的问题。

答案 5 :(得分:4)

很难说没有看到更多的代码,但它看起来与这个问题有关:UnicodeDecodeError on attempt to save file through django default filebased backend

通过阅读Django票证,您似乎应该遵循类似于“如果您得到UnicodeEncodeError”的部署文档的内容:
https://docs.djangoproject.com/en/1.4/howto/deployment/modpython/#if-you-get-a-unicodeencodeerror

(我知道这是针对Apache / mod_python的,但我的猜测是文件系统编码的根本问题不是UTF-8,使用nginx时也有类似的修复)

编辑: 据我所知,这个nginx模块将是等效的修复:http://wiki.nginx.org/NginxHttpCharsetModule

答案 6 :(得分:4)

如前所述,它与语言环境有关。例如,如果您使用gunicorn来为django application提供服务,则可能会有一个init.d脚本(或者像我一样的runit脚本),您可以在其中设置区域设置。

要解决带文件上传的UnicodeEncodeError,请在运行应用程序的脚本中添加export LC_ALL=en_US.UTF8之类的内容。

例如,这是我的(使用gunicornrunit):

#!/bin/bash
export LC_ALL=en_US.UTF8
cd /path/to/app/projectname
exec gunicorn_django -b localhost:8000 --workers=2

此外,您可以在视图中使用此功能检查模板中的区域设置:

import locale
data_to_tpl = {'loc': locale.getlocale(), 'lod_def': locale.getdefaultlocale()}

只需在模板中显示{{loc}} - {{loc_def}}

您将获得有关区域设置的更多信息!这对我来说非常有用。

答案 7 :(得分:4)

避免重写代码的另一个有用选项是更改python的默认编码。

如果您正在使用virtualenv,则可以更改(或创建,如果不存在)env/lib/python2.7/sitecustomize.py并添加:

import sys
sys.setdefaultencoding('utf-8')

或者,如果您在生产系统中,则可以对/usr/lib/python2.7/sitecustomize.py

执行相同的操作

答案 8 :(得分:3)

如果您正在使用django和python 2.7,则会为我修复它:

@python_2_unicode_compatible
class Utente(models.Model):

请参阅https://docs.djangoproject.com/en/dev/ref/utils/#django.utils.encoding.python_2_unicode_compatible

答案 9 :(得分:3)

使用python 2.7.8和Django 1.7,我通过导入解决了我的问题:

from __future__ import unicode_literals

并使用force_text()

from django.utils.encoding import force_text

答案 10 :(得分:2)

只是建立在这个线程及其他人的答案上......

我在genericpath.py遇到同样的问题,在尝试上传带有非ASCII字符的文件名时会出现UnicodeEncodeError。

我正在使用nginx,uwsgi和django和python 2.7。

一切都在本地工作,但不在服务器上

以下是我采取的步骤 1.添加到/etc/nginx/nginx.conf(没有解决问题)

http {
    charset utf-8;
}
  1. 我将此行添加到etc / default / locale(没有解决问题)

    LANGUAGE="en_US.UTF-8"

  2. 我按照标题'成功'中列出的说明进行操作。 https://code.djangoproject.com/wiki/ExpectedTestFailures(没有解决问题)

    aptitude install language-pack-en-base
    
  3. 找到这张票 https://code.djangoproject.com/ticket/17816 建议在服务器上测试视图信息

  4. 发生的事情

    在你看来

    import locale
    locales = "Current locale: %s %s -- Default locale: %s %s" % (locale.getlocale() + locale.getdefaultlocale())
    

    在您的模板中

    {{ locales }}
    

    对我来说,问题是我的Ubuntu服务器上没有语言环境和默认语言环境(虽然我确实在我的本地OSX开发机器上有它们)然后使用python无法正确上传非ASCII文件名/路径的文件提出UnicodeEncodeError,但仅在生产服务器上。

    <强>解决方案

    我将此添加到我的网站和我的网站管理员uwsgi配置文件中 例如/ etc / uwsgi-emperor / vassals / my-site-config-ini file

    env = LANG=en_US.utf8
    

答案 11 :(得分:0)

没有一个答案对我有用(在Ubuntu上使用Apache和Django 1.10);我选择从文件名中删除重音(normalize),如下所示:

def remove_accents(value):
    nkfd_form = unicodedata.normalize('NFKD', str(value))
    return "".join([c for c in nkfd_form if not unicodedata.combining(c)])

uploaded_file = self.cleaned_data['data']

# We need to remove accents to get rid of "UnicodeEncodeError: 'ascii' codec can't encode character" on Ubuntu
uploaded_file.name = remove_accents(uploaded_file.name)