2012-02-09 15 views
6

La mia domanda è simile a quella riportata here, ma la soluzione proposta non funziona per me. Sto cercando di caricare un file chiamato "Testaråäö.txt" tramite l'app di amministrazione Django.UnicodeEncodeError durante il caricamento di file nell'amministratore di Django

Sto eseguendo Django 1.3.1 con Gunicorn 0.13.4 e Nginx 0.7.6.7 su un server Debian 6. Il database è PostgreSQL 8.4.9. Altri dati Unicode vengono salvati nel database senza problemi, quindi suppongo che il problema debba essere in qualche modo con il filesystem.

Ho impostato

http { 
    charset utf-8; 
} 

nel mio nginx.conf. LC_ALL e LANG è impostato su 'sv_SE.UTF-8'. L'esecuzione di "locale" lo verifica. Ho anche provato a impostare LC_ALL e LANG nel mio script init nginx solo per assicurarmi che le impostazioni locali siano impostate correttamente.

Ecco il traceback:

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: Ho provato a fare funzionare Gunicorn con il debug attivato, ei upload di file senza alcun problema a tutti. Suppongo che questo debba significare che il problema è con Nginx. Ancora mi batte dove cercare, però. Qui ci sono le intestazioni di risposta prime da Gunicorn e Nginx, se ha un senso:

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

Hai mai ottenere una correzione per questo? come stai iniziando il gunicorn? – ashwoods

+0

Siamo spiacenti, no. Ho detto al mio cliente di evitare semplicemente l'uso di caratteri unicode fino a quando non sono riuscito a trovare una soluzione (che assomiglia sempre di più alla migrazione su un altro server). Sto usando Supervisor per avviare gunicorn. –

+0

Succede anche per noi. Stessa configurazione - NginX, Supervisor, Gunicorn che eseguono l'app Django.Ho sprecato due ore cercando di sistemarlo, ho provato tutte le raccomandazioni ovunque su internet senza fortuna. Eventualmente, qualcuno troverà un modo per farlo funzionare alla fine. – xaralis

risposta

6

Sembra che si tratta di un problema comune che il servizio che gestisce il servizio django, sia esso apache, gunicorn + supervisor, daemontools, ecc. non usa sempre le variabili di ambiente corrette.

In questo caso, gunicorn viene avviato da supervisore, quindi bisogna dire esplicitamente supervisore per usare utf-8 utilizzando l'opzione di ambiente:

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

Sembra in Supervisor 3.0a8 (la versione fornita in Debian Squeeze) l'opzione 'environment' deve essere specificata globalmente nella sezione' [supervisord] 'del file di configurazione. Non è riconosciuto nelle sezioni '[program: *]'. – akaihola

+0

akaihola grazie, ho passato le ultime 3 ore a cercarlo ..... – migajek

+0

grazie, ha funzionato alla grande. – Marco

1

ho avuto lo stesso problema con genericpath.py dando un UnicodeEncodeError quando si tenta di caricare un nome file con caratteri non ASCII.

Stavo usando nginx, uwsgi e django con python 2.7.

Tutto stava funzionando OK localmente ma non sul server

qui sono i passi che ho preso:

  1. aggiunto al file/etc/nginx/nginx.conf (non risolvere il problema)

    http { 
        charset utf-8; 
    } 
    
  2. Ho aggiunto questa linea al etc/default/locale (non risolvere il problema)

    LANGUAGE="en_US.UTF-8" 
    
  3. Ho seguito le istruzioni qui elencate alla voce 'Successo' https://code.djangoproject.com/wiki/ExpectedTestFailures (non risolvere il problema)

    aptitude install language-pack-en-base 
    
  4. Trovato in questo biglietto https://code.djangoproject.com/ticket/17816 che ha suggerito la sperimentazione di un vista sul server per ciò che stava accadendo con informazioni locale vista

Django

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 Template

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

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

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

Per me, il problema era che Non avevo locale e nessuna localizzazione predefinita sul mio server Ubuntu (anche se li avevo sul mio computer locale OSX) quindi file con file non ASCII i nomi/percorsi non verranno caricati correttamente con python che genera un errore UnicodeEncodeError, ma solo sul server di produzione.

Soluzione

ho aggiunto questo al mio sito di amministrazione uwsgi file di configurazione esempio sia il mio sito e/Etc/uwsgi-imperatore/vassalli/file di my-sito-config-ini

env = LANG=en_US.utf8 

Aggiornamento

Dopo passare a finestra mobile Ho iniziato a ricevere di nuovo lo stesso errore. Dopo averlo esaminato ulteriormente, mi sono reso conto nell'istanza uwsgi django import sys; sys.getfilesystemencoding() o {{ file_system_encoding }} precedente restituire ANSI_X3.4-1968, tuttavia se avessi avviato la mia istanza python e avessi eseguito import sys; sys.getfilesystemencoding() avrei ottenuto UTF-8. Il formato ANSI_X3.4-1968 è ciò che sta generando l'UnicodeEncodeError.

Quindi, oltre alla soluzione uwsgi elencati in questa risposta di cui sopra, ho anche dovuto aggiungere questo al mio Django 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 

Oppure, se non si utilizza finestra mobile si può semplicemente eseguire questo nella shell

$ export LANG=en_US.UTF-8 

Quindi eseguire il comando RUN sopra (ma senza RUN).

Riferimenti:

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

Questa è una grande risposta, con una guida alla diagnosi passo-passo. Non so perché abbia così pochi voti positivi. Si noti che in caso di Ubuntu è necessario un pacchetto linguistico per la propria lingua. Quindi, se impostate l'env 'LANG' per dire spagnolo, non si' aptitude install language-pack-es-base'. Simile per tutte le altre lingue. –

Problemi correlati