3 votes

UnicodeEncodeError lors du téléchargement de fichiers dans l'administration Django

Note : J'ai posé cette question sur StackOverflow, mais je réalise que c'est peut-être un endroit plus approprié pour poser ce genre de question.

J'essaie de télécharger un fichier appelé 'Testaråäö.txt' via l'application d'administration de Django.

Je fais tourner Django 1.3.1 avec Gunicorn 0.13.4 et Nginx 0.7.6.7 sur un serveur Debian 6. La base de données est PostgreSQL 8.4.9. D'autres données Unicode sont enregistrées dans la base de données sans problème, donc je suppose que le problème doit être avec le système de fichiers d'une certaine manière.

J'ai défini

http {
    charset utf-8;
}

dans mon nginx.conf. LC_ALL et LANG sont définis sur 'sv_SE.UTF-8'. En exécutant 'locale', cela le vérifie. J'ai même essayé de définir LC_ALL et LANG dans mon script d'initialisation nginx juste pour m'assurer que la locale est définie correctement.

Voici la trace de la pile :

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)

J'ai essayé de faire tourner Gunicorn avec le débogage activé, et le fichier se télécharge sans aucun problème du tout. Je suppose que cela doit signifier que le problème vient de Nginx. Cependant, je ne sais pas vraiment où chercher. Voici les en-têtes de réponse bruts de Gunicorn et de Nginx, si cela a du sens :

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

MISE À JOUR : locale.getpreferredencoding() et sys.getfilesystemencoding() renvoient 'UTF-8'. locale.getdefaultlocale() renvoie ('sv_SE', 'UTF8'). Cela me semble correct, donc je ne suis toujours pas sûr de pourquoi j'obtiens ces erreurs.

2voto

lukeaus Points 121

J'ai rencontré le même problème avec genericpath.py donnant une UnicodeEncodeError lors de la tentative de téléchargement d'un fichier avec des caractères non ASCII dans le nom.

J'utilisais nginx, uwsgi et django avec python 2.7.

Tout fonctionnait correctement en local mais pas sur le serveur.

Voici les étapes que j'ai suivies 1. ajouté à /etc/nginx/nginx.conf (n'a pas résolu le problème)

http {
    charset utf-8;
}
  1. J'ai ajouté cette ligne à etc/default/locale (n'a pas résolu le problème)

LANGUAGE="en_US.UTF-8"

  1. J'ai suivi les instructions répertoriées ici sous le titre 'Success' https://code.djangoproject.com/wiki/ExpectedTestFailures (n'a pas résolu le problème)

    aptitude install language-pack-en-base
  2. Je suis tombé sur ce ticket https://code.djangoproject.com/ticket/17816 qui suggérait de tester une vue sur le serveur pour voir ce qui se passait avec les informations de localisation

Dans votre vue

import locale
locales = "Locale actuelle : %s %s -- Locale par défaut : %s %s" % (locale.getlocale() + locale.getdefaultlocale())

Dans votre template

{{ locales }}

Pour moi, le problème était que je n'avais pas de localisation et aucun local par défaut sur mon serveur Ubuntu (bien que je les avais sur ma machine de développement OSX local), alors les fichiers avec des noms/chemins de fichier non ASCII ne se téléchargeront pas correctement avec python levant une UnicodeEncodeError, mais seulement sur le serveur de production.

Solution

J'ai ajouté ceci à la fois à mes fichiers de configuration uwsgi pour mon site et mon site admin par exemple. /etc/uwsgi-emperor/vassals/fichier-de-config-mon-site-ini

env = LANG=en_US.utf8

1voto

lxmmxl56 Points 111

Juste au cas où quelqu'un arrive ici avec Apache utilisant mod_wsgi, cela peut être résolu en ajoutant les options lang et locale à la ligne WSGIDaemonProcess dans le fichier de configuration de votre site.

Devrait normalement être défini sur en_US.UTF-8 selon la documentation :

https://modwsgi.readthedocs.io/en/develop/configuration-directives/WSGIDaemonProcess.html

Comme ceci :

lang=en_US.UTF-8 locale=en_US.UTF-8

Par exemple :

WSGIDaemonProcess processName python-home=/path/to/venv python-path=/path/to/mydjangoproject lang=en_US.UTF-8 locale=en_US.UTF-8

Après avoir ajouté ces options, redémarrez Apache et vous devriez être prêt à partir.

0voto

Jader Dias Points 23461

J'ai rencontré le même problème et j'ai trouvé les solutions pour mes cas (je suis sous Ubuntu).

J'ai trouvé un bon fil de discussion non résolu ici, où Karen donne des informations utiles :

https://groups.google.com/forum/?fromgroups#!topic/django-users/hwNL7i6IeIY

ce qui m'a amené à ceci :

https://code.djangoproject.com/wiki/ExpectedTestFailures

J'ai installé le "language-pack" manquant pour Ubuntu. et j'ai exécuté en tant que root dans un terminal :

locale-gen en_US.UTF-8

et maintenant ça fonctionne.

On dirait que, dans les couches de bas niveau de Python, quelque chose appelé Glibc a besoin de fichiers compilés générés par locale-gen pour fonctionner correctement.

J'ai regardé sur http://packages.debian.org et il n'y a pas de package de ce type dans Debian.

Essayez d'exécuter ce qui suit et redémarrez votre démon avant de réessayer :

locale-gen sv_SE.UTF-8

ou peut-être installer des packages spécifiques à la localisation/langue de Debian, s'il y en a.

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X