Je travaille sur un nouveau site Django et, après avoir migré dans une pile de données, j'ai commencé à utiliser un DjangoUnicodeDecodeError très frustrant. Le mauvais personnage en question est un \ xe8 (e-grave).Codage de caractères Django
Il y a deux questions épineuses:
Il arrive que dans le serveur de production, l'exécution d'un processus fcgi rieuses Apache (exécutant le même code avec la même base de données sur le serveur dev Django n'a pas de problème)
La trace de pile en question est entièrement dans le code Django. Il se produit dans le site d'administration (ailleurs aussi) lors de la récupération d'un élément à afficher, bien que le champ qui contient le mauvais caractère n'est pas réellement rendu.
Je ne suis même pas entièrement sûr de savoir où commencer le débogage, à moins d'essayer de supprimer les caractères incriminés manuellement. Je suppose qu'il s'agit d'un problème de configuration, car il est spécifique à l'environnement, mais je ne suis pas sûr de savoir par où commencer.
EDIT: Comme Daniel Roseman a souligné, l'erreur est presque certainement dans la méthode unicode - ou, plus précisément, une autre méthode qui l'appelle. Notez que les caractères incriminés sont dans un champ non référencé du tout dans le code ici. Je suppose que l'exception est levée dans une méthode qui construit l'objet à partir du résultat db - si le queryset n'est jamais évalué (par exemple si self.enabled) il n'y a pas d'erreur. Voici le code:
def get_blocking_events(self):
return Event.objects.filter(<get a set of events>)
def get_blocking_reason(self):
blockers = self.get_blocking_events()
label = u''
if not self.enabled:
label = u'Sponsor disabled'
elif len(blockers) > 0:
label = u'Pending follow-up: "{0}" ({1})'.format(blockers[0],blockers[0].creator.email)
if len(blockers) > 1:
label += u" and {0} other event".format(len(blockers)-1)
if len(blockers) > 2:
label += u"s"
return label
def __unicode__(self):
label = self.name
blocking_msg = self.get_blocking_reason()
if len(blocking_msg):
label += u" ({0})".format(blocking_msg)
return label
Voici la queue de la trace de la pile, pour le plaisir:
File "/opt/opt.LOCAL/Django-1.2.1/django/template/__init__.py", line 954, in render
dict = func(*args)
File "/opt/opt.LOCAL/Django-1.2.1/django/contrib/admin/templatetags/admin_list.py", line 209, in result_list
'results': list(results(cl))}
File "/opt/opt.LOCAL/Django-1.2.1/django/contrib/admin/templatetags/admin_list.py", line 201, in results
yield list(items_for_result(cl, res, None))
File "/opt/opt.LOCAL/Django-1.2.1/django/contrib/admin/templatetags/admin_list.py", line 138, in items_for_result
f, attr, value = lookup_field(field_name, result, cl.model_admin)
File "/opt/opt.LOCAL/Django-1.2.1/django/contrib/admin/util.py", line 270, in lookup_field
value = attr()
File "/opt/opt.LOCAL/Django-1.2.1/django/db/models/base.py", line 352, in __str__
return force_unicode(self).encode('utf-8')
File "/opt/opt.LOCAL/Django-1.2.1/django/utils/encoding.py", line 88, in force_unicode
raise DjangoUnicodeDecodeError(s, *e.args)
DjangoUnicodeDecodeError: 'utf8' codec can't decode bytes in position 956-958: invalid data. You passed in <Sponsor: [Bad Unicode data]> (<class 'SJP.alcohol.models.Sponsor'>)
Le coupable habituel dans ces circonstances est la méthode '__unicode__' du modèle. Pouvez-vous nous montrer le code? –
Qu'en est-il des données dans la base de données - vos tables utilisent-elles UTF8 ou un codage ISO Latin? –
La base de données est MS SQL Server, donc je crois comprendre qu'il n'y a pas d'encodage à l'échelle de la base de données; cependant, la colonne en question est un nvarchar, ce qui signifie que les données sont encodées en UTF-16. Je noterai également que je n'ai aucun problème à lire exactement la même base de données avec le même code d'application via le serveur de développement django. –