2012-02-09 3 views
6

Мой вопрос похож на тот, который был указан here, но предлагаемое решение не работает для меня. Я пытаюсь загрузить файл под названием «Testaråäö.txt» через приложение администратора Django.UnicodeEncodeError при загрузке файлов в Django admin

Я запускаю Django 1.3.1 с Gunicorn 0.13.4 и Nginx 0.7.6.7 на сервере Debian 6. База данных - PostgreSQL 8.4.9. Другие данные Unicode сохраняются в базе данных без проблем, поэтому я думаю, что проблема должна быть в файловой системе каким-то образом.

Я установил

http { 
    charset utf-8; 
} 

в моем nginx.conf. LC_ALL и LANG установлены на 'sv_SE.UTF-8'. Выполнение «locale» проверяет это. Я даже попытался установить LC_ALL и LANG в моем сценарии инициализации nginx, чтобы убедиться, что локаль установлена ​​правильно.

Вот отслеживающий:

Traceback (most recent call last): 

File "/srv/.virtualenvs/letebo/lib/python2.6/site-packages/django/core/handlers/base.py", line 111, in get_response 
response = callback(request, *callback_args, **callback_kwargs) 

File "/srv/.virtualenvs/letebo/lib/python2.6/site-packages/django/contrib/admin/options.py", line 307, in wrapper 
return self.admin_site.admin_view(view)(*args, **kwargs) 

File "/srv/.virtualenvs/letebo/lib/python2.6/site-packages/django/utils/decorators.py", line 93, in _wrapped_view 
response = view_func(request, *args, **kwargs) 

File "/srv/.virtualenvs/letebo/lib/python2.6/site-packages/django/views/decorators/cache.py", line 79, in _wrapped_view_func 
response = view_func(request, *args, **kwargs) 

File "/srv/.virtualenvs/letebo/lib/python2.6/site-packages/django/contrib/admin/sites.py", line 197, in inner 
return view(request, *args, **kwargs) 

File "/srv/django/letebo/app/cms/admin.py", line 81, in change_view 
return super(PageAdmin, self).change_view(request, obj_id) 

File "/srv/.virtualenvs/letebo/lib/python2.6/site-packages/django/utils/decorators.py", line 28, in _wrapper 
return bound_func(*args, **kwargs) 

File "/srv/.virtualenvs/letebo/lib/python2.6/site-packages/django/utils/decorators.py", line 93, in _wrapped_view 
response = view_func(request, *args, **kwargs) 

File "/srv/.virtualenvs/letebo/lib/python2.6/site-packages/django/utils/decorators.py", line 24, in bound_func 
return func(self, *args2, **kwargs2) 

File "/srv/.virtualenvs/letebo/lib/python2.6/site-packages/django/db/transaction.py", line 217, in inner 
res = func(*args, **kwargs) 

File "/srv/.virtualenvs/letebo/lib/python2.6/site-packages/django/contrib/admin/options.py", line 985, in change_view 
self.save_formset(request, form, formset, change=True) 

File "/srv/.virtualenvs/letebo/lib/python2.6/site-packages/django/contrib/admin/options.py", line 677, in save_formset 
formset.save() 

File "/srv/.virtualenvs/letebo/lib/python2.6/site-packages/django/forms/models.py", line 482, in save 
return self.save_existing_objects(commit) + self.save_new_objects(commit) 

File "/srv/.virtualenvs/letebo/lib/python2.6/site-packages/django/forms/models.py", line 613, in save_new_objects 
self.new_objects.append(self.save_new(form, commit=commit)) 

File "/srv/.virtualenvs/letebo/lib/python2.6/site-packages/django/forms/models.py", line 717, in save_new 
obj.save() 

File "/srv/.virtualenvs/letebo/lib/python2.6/site-packages/django/db/models/base.py", line 460, in save 
self.save_base(using=using, force_insert=force_insert, force_update=force_update) 

File "/srv/.virtualenvs/letebo/lib/python2.6/site-packages/django/db/models/base.py", line 504, in save_base 
self.save_base(cls=parent, origin=org, using=using) 

File "/srv/.virtualenvs/letebo/lib/python2.6/site-packages/django/db/models/base.py", line 543, in save_base 
for f in meta.local_fields if not isinstance(f, AutoField)] 

File "/srv/.virtualenvs/letebo/lib/python2.6/site-packages/django/db/models/fields/files.py", line 255, in pre_save 
file.save(file.name, file, save=False) 

File "/srv/.virtualenvs/letebo/lib/python2.6/site-packages/django/db/models/fields/files.py", line 92, in save 
self.name = self.storage.save(name, content) 

File "/srv/.virtualenvs/letebo/lib/python2.6/site-packages/django/core/files/storage.py", line 48, in save 
name = self.get_available_name(name) 

File "/srv/.virtualenvs/letebo/lib/python2.6/site-packages/django/core/files/storage.py", line 74, in get_available_name 
while self.exists(name): 

File "/srv/.virtualenvs/letebo/lib/python2.6/site-packages/django/core/files/storage.py", line 218, in exists 
return os.path.exists(self.path(name)) 

File "/srv/.virtualenvs/letebo/lib/python2.6/genericpath.py", line 18, in exists 
st = os.stat(path) 

UnicodeEncodeError: 'ascii' codec can't encode characters in position 52-54: ordinal not in range(128) 

UPDATE: Я попытался запустить Gunicorn отладки включен, и файл загрузки без каких-либо проблем на всех. Полагаю, это должно означать, что проблема связана с Nginx. Тем не менее, все равно бьется, где искать. Вот исходные заголовки ответа от Gunicorn и Nginx, если это имеет смысл:

Gunicorn:

HTTP/1.1 302 FOUND 
Server: gunicorn/0.13.4 
Date: Thu, 09 Feb 2012 14:50:27 GMT 
Connection: close 
Transfer-Encoding: chunked 
Expires: Thu, 09 Feb 2012 14:50:27 GMT 
Vary: Cookie 
Last-Modified: Thu, 09 Feb 2012 14:50:27 GMT 
Location: http://my-server.se:8000/admin/cms/page/15/ 
Cache-Control: max-age=0 
Content-Type: text/html; charset=utf-8 
Set-Cookie: messages="yada yada yada"; Path=/ 

Nginx:

HTTP/1.1 500 INTERNAL SERVER ERROR 
Server: nginx/0.7.67 
Date: Thu, 09 Feb 2012 14:50:57 GMT 
Content-Type: text/html; charset=utf-8 
Transfer-Encoding: chunked 
Connection: close 
Vary: Cookie 

500 
+0

вы когда-нибудь исправить это? как вы начинаете стрельбу? – ashwoods

+0

Извините, нет. Я сказал своему клиенту просто избегать использования символов Юникода, пока не найду решение (которое все больше похоже на перенос на другой сервер). Я использую Supervisor для запуска оружия. –

+0

Это происходит и для нас. Та же настройка - NginX, Супервизор, Gunicorn, запускающий приложение Django.Я потратил два часа на то, чтобы исправить это, пробовал все рекомендации повсюду в Интернете без везения. Надеюсь, кто-то найдет способ получить эту работу в конечном итоге. – xaralis

ответ

6

Похоже, что это общая проблема, что службы который запускает службу django, будь то apache, gunicorn + supervisor, daemontools и т. д. ... не всегда использует правильные переменные среды.

В этом случае gunicorn запускается руководителем, поэтому вы должны явно указать супервизора использовать UTF-8 с помощью параметра среды:

environment=LANG=en_US.UTF-8, LC_ALL=en_US.UTF-8, LC_LANG=en_US.UTF-8 
+2

Похоже, что в Supervisor 3.0a8 (версия, представленная в Debian Squeeze) параметр 'environment' должен быть указан глобально в разделе' [supervisord] 'файла конфигурации. Он не распознается в разделах '[program: *]'. – akaihola

+0

akaihola спасибо, я потратил последние 3 часа на то, чтобы найти ..... – migajek

+0

спасибо, это сработало отлично. – Marco

1

я имел такую ​​же проблему с genericpath.py давая UnicodeEncodeError при попытке загрузить имя файла без символов ASCII.

Я использовал nginx, uwsgi и django с python 2.7.

Все работает нормально локально, но не на сервере

Вот шаги, которые я взял:

  1. добавлены в/и т.д./Nginx/Nginx.конф (не решить эту проблему)

    http { 
        charset utf-8; 
    } 
    
  2. Я добавил эту строку и т.д./по умолчанию/локали (не устранило проблему)

    LANGUAGE="en_US.UTF-8" 
    
  3. Я следовал инструкциям здесь перечислены под заголовком 'Успех' https://code.djangoproject.com/wiki/ExpectedTestFailures (не устранило проблему)

    aptitude install language-pack-en-base 
    
  4. Найдено по этому билету https://code.djangoproject.com/ticket/17816 который предложил испытывать взгляд на сервере к тому, что происходит с информацией локали

Джанго вид

import locale 

def locales(request): 
    """Display the locales""" 
    locales = "Current locale: %s %s -- Default locale: %s %s" % (
     locale.getlocale() + locale.getdefaultlocale()) 
    default_encoding = sys.getdefaultencoding() 
    file_system_encoding = sys.getfilesystemencoding() 

    context = { 
     'locales': locales, 
     'default_encoding': default_encoding, 
     'file_system_encoding': file_system_encoding, # affects file uploads 
    } 
    return render(request, 'testing/locales.html', context) 

Django шаблон

<h2>Locales</h2> 
<p>{{ locales }}</p> 

<h2>Default Encoding</h2> 
<p>{{ default_encoding }}</p> 

<h2>File System Encoding</h2> 
<p>{{ file_system_encoding }}</p> 

Для меня вопрос в том, что У меня не было локали и локали по умолчанию на моем сервере Ubuntu (хотя у меня их были на моей локальной машине OSX dev), тогда файлы с файлом без ASCII имена/пути не будут правильно загружаться с помощью python, создающего UnicodeEncodeError, но только на производственном сервере.

Решение

Я добавил это как мой сайт и мой администратор сайта uwsgi конфигурационные файлы например/И т.д./uwsgi-император/вассалов/мой сайт-конфиг-файл INI

env = LANG=en_US.utf8 

Update

После перехода к докер я снова начал получать ту же ошибку. Изучив его дальше, я понял, что в экземпляре uwsgi django import sys; sys.getfilesystemencoding() или {{ file_system_encoding }} выше возвращался ANSI_X3.4-1968, однако, если бы я начал свой собственный экземпляр python и запустил import sys; sys.getfilesystemencoding(), я получил бы UTF-8. Формат ANSI_X3.4-1968 - это то, что бросает UnicodeEncodeError.

Таким образом, в дополнение к uwsgi решения, перечисленные в этом ответе выше, я также должен был добавить это к моему Джанго dockerfile

ENV LANG en_US.UTF-8 
RUN apt-get update && install -y locales && \ 
    sed -i -e "s/# $LANG.*/$LANG UTF-8/" /etc/locale.gen && \ 
    locale-gen --purge &&\ 
    update-locale LANG=$LANG 

Или, если вы не используете докер вы можете просто запустить это в оболочке

$ export LANG=en_US.UTF-8 

Затем выполните команду RUN выше (но без RUN).

Ссылки:

http://stackoverflow.com/a/37246853/3003438 
https://docs.djangoproject.com/en/dev/howto/deployment/wsgi/uwsgi/ 
+0

Это отличный ответ с пошаговым руководством по диагностике. Я не знаю, почему у него так мало голосов. Обратите внимание, что в случае Ubuntu вам нужен языковой пакет для вашего языка. Поэтому, если установить «LANG» env, чтобы сказать «испанский», вы не устанавливаете «язык установки-пакет-es-base». Аналогичен для всех других языков. –