Erreur d'encodage

Le couple Django, Python3, MySQL: Quelle horreur !

L'auteur de ce sujet a trouvé une solution à son problème.
Auteur du sujet

Salut à tous ! Pour un projet de stage, j'ai décidé d'utiliser Django 1.8 avec Python 3.2 et MySQL 5.5. C'est une grosse erreur que j'ai fait là, car je ne tombe que sur des galères liés à ces 3 technologies combinées.

Bref, aujourd'hui je viens vous voir pour discuter d'un problème que je n'arrive pas à résoudre malgré une journée de recherche …

J'ai une erreur d'encodage lorsque, via l'interface d'administration, j'essaye d'ajouter un élément dans ma base qui contient un champ null (ou vide). Voici le message d'erreur :

1
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xe9 in position 1170: invalid continuation byte

Cette erreur ne fait pas crasher l'application, mais ne génère rien dans ma base de donnée. Ah, oui j'allais oublier, j'utilise le driver 'pymysql'.

Je vous remercie par avance. À une prochaine !

+0 -0
Auteur du sujet

D'accord :)

Ça risque d’être un peu long (désolé si c'est peut commenté, mais c'est un 'brouillon') :

models.py

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
from django.db import models
from polymorphic import PolymorphicModel

# Doc: http://www.apidev.fr/blog/2012/01/12/heritage-de-modele-avec-django/

class User(PolymorphicModel):
    username = models.CharField(primary_key=True, max_length=255)
    lastname = models.CharField(max_length=255)
    firstname = models.CharField(max_length=255)

    def __str__(self):
        return "{0} ({1} {2})".format(self.username, self.lastname, self.firstname)


class Admin(User):
    pass


class Teacher(User):
    groups = models.ManyToManyField('Group', blank=True)

    def __str__(self):
        return "{0} ({1})".format(super(Teacher, self).__str__(), self.group)


class Student(User):
    group = models.ForeignKey('Group', null=True, blank=True, on_delete=models.SET_NULL)

    def __str__(self):
        return "{0} ({1})".format(super(Student, self).__str__(), self.group)


class Group(models.Model):
    name = models.CharField(primary_key=True, max_length=255)
    exercises = models.ManyToManyField('Exercise', blank=True)

    def __str__(self):
        return self.group_name


class Activity(models.Model):  # Une activité est composée de plusieurs exercices
    title = models.CharField(primary_key=True, max_length=255)
    date = models.DateTimeField(auto_now=True)
    multi_attempts = models.BooleanField()  # tentatives multiples ?
    interactive_correction = models.BooleanField()  # correction interactive ? utile en materelle

    teacher = models.ForeignKey('Teacher')

    def __str__(self):
        return "{0} ({1})".format(self.title, self.date)


class Exercise(models.Model):
    order_json = models.TextField() # Consigne
    exercise_json = models.TextField() #TODO
    activity = models.ForeignKey('Activity')


class CorrectionElement(models.Model):
    index = models.IntegerField()
    content = models.TextField()
    exercise = models.ForeignKey('Exercise')


class Reply(models.Model):
    date = models.DateTimeField(auto_now=True)

    exercise = models.ForeignKey('Exercise', null=True, blank=True, on_delete=models.SET_NULL)# un exercice peut etre supprimé, du coup il faut stocker le score
    student = models.ForeignKey('Student')

    index = models.IntegerField()
    content = models.TextField()



    def __str__(self):
        return "{0} {1} ({2})".format(self.student, self.exercise, self.date)

admin.py

1
2
3
4
5
6
7
from django.contrib import admin
from .models import *

admin.site.register(Admin)
admin.site.register(Teacher)
admin.site.register(Student)
admin.site.register(Group)

Voila :)

L'erreur apparaît, par exemple, quand je veux ajouter un Group qui n'a pas d'exercises.

Édité par DigitalSuricate

+0 -0
Staff

Cette réponse a aidé l'auteur du sujet

Alors, tu as déjà un problème ici :

1
2
def __str__(self):
        return self.group_name

group_name n'existe pas dans ton modèle, c'est plutot name. C'est le genre de chose qui peut générer une erreur, mais l'erreur que tu obtiens ne ressemble pas à ça.

Ensuite, pour la ligne :

1
exercises = models.ManyToManyField('Exercise', blank=True)

Essaye de la remplacer par :

1
exercises = models.ManyToManyField('Exercise', blank=True, null=True)

Et dis moi si tu as toujours les même erreurs

Cette réponse a aidé l'auteur du sujet

Aussi ce que dit la Documentation, mais je ne connais pas Django, c'est d'utiliser le décorateur python_2_unicode_compatible (ce que tu fais pas) avec la méthode str (ce que tu fais) de ta classe. Par exemple en suivant les conseils de firm1, ça donnerait

1
2
3
4
5
6
7
@python_2_unicode_compatible
class Group(models.Model):
    name = models.CharField(primary_key=True, max_length=255)
    exercises = models.ManyToManyField('Exercise', blank=True)

    def __str__(self):
        return self.name

Voir documentation, ça évite les embrouilles je pense

+1 -0
Auteur du sujet

Tout d’abord merci à vous deux.

Alors, tu as déjà un problème ici :

1
2
def __str__(self):
        return self.group_name

group_name n'existe pas dans ton modèle, c'est plutot name. C'est le genre de chose qui peut générer une erreur, mais l'erreur que tu obtiens ne ressemble pas à ça.

Ensuite, pour la ligne :

1
exercises = models.ManyToManyField('Exercise', blank=True)

Essaye de la remplacer par :

1
exercises = models.ManyToManyField('Exercise', blank=True, null=True)

Et dis moi si tu as toujours les même erreurs

firm1

Je ne suis pas sûr que ce soit utile :

1
2
3
WARNINGS:
main.Group.exercises: (fields.W340) null has no effect on ManyToManyField.
main.Teacher.groups: (fields.W340) null has no effect on ManyToManyField.

Mais, ça à résolu le problème. Encore une 'bizarrerie' :D

Quoi que c'est peut être l'histoire du 'group_name', je ne sais pas, j'ai corrigé les deux en même temps.

Aussi ce que dit la Documentation, mais je ne connais pas Django, c'est d'utiliser le décorateur python_2_unicode_compatible (ce que tu fais pas) avec la méthode str (ce que tu fais) de ta classe. Par exemple en suivant les conseils de firm1, ça donnerait

1
2
3
4
5
6
7
@python_2_unicode_compatible
class Group(models.Model):
    name = models.CharField(primary_key=True, max_length=255)
    exercises = models.ManyToManyField('Exercise', blank=True)

    def __str__(self):
        return self.name

Voir documentation, ça évite les embrouilles je pense

fred1599

J’adore cette doc en français, je la parcoure en permanence, bizarre que je ne sois jamais tombé sur cette page …

Enfin bon, de toute façon j'utilise Python 3, donc je n'ai pas besoin de ce décorateur, mais ça peut toujours être utile à ceux qui utilisent encore Python 2 (comme Zeste de Savoir) :)

H.S: Au faite les contributeurs de Zeste de Savoir, ont-il prévus de passer à Python 3 ?

P.S: L'erreur d'encodage vient bien du faite que je me sert d'un attribut qui n'existe pas dans str, j'avais fait la même bourde dans Teacher et j'ai obtenue la même erreur d'encodage.

Django n'est pas très clair sur ce coup là, rien n'indiqué que l'erreur venait de là …

Édité par DigitalSuricate

+0 -0
Vous devez être connecté pour pouvoir poster un message.
Connexion

Pas encore inscrit ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte