Bienvenue sur IndexError.

Ici vous pouvez poser des questions sur Python et le Framework Django.

Mais aussi sur les technos front comme React, Angular, Typescript et Javascript en général.

Consultez la FAQ pour améliorer vos chances d'avoir des réponses à vos questions.

django. admin forms. Tous les caractères unicode ne sont pas pris en compte.

+2 votes

J'utilise les formulaires standards de l'interface admin de django, pour créer et éditer des objets, avec des champs de type models.CharField, models.TextField, ...

Je peux saisir dans les champs certains caractères unicode particuliers, par exemple tout ceux là :
∞ ☁ ☇ ☂ ☔ ☈ ☉ ☼ ☀ ☽ ☾ ☿ ♀ ♁ ♂ ♃ ♄ ♅ ♆ ♇ ⚳ ⚷ ♈ ♓ ⛄ ❄
Ils se réaffichent correctement dans l'interface admin, ainsi que dans mes pages web.

Mais d'autres caractères ne passent pas. Par exemple le smiley.

J'ai regardé dans la base de donnée (mysql). J'ai l'impression que les smileys ne sont mêmes pas écrits dans l'enregistrement de la table.

Est-ce que ça viendrait de ma librairie unicode qui n'a pas été mise à jour depuis un certain temps ?
Si oui, il faudrait faire comment ? apt-get ? pip install upgrade ? autre chose ?

Désolé, je ne peux pas vous montrer des exemples de smiley qui ne marchent pas. De manière assez amusante, ils ne passent pas non plus dans IndexError.

Si j'écris un smiley, tout le texte qui vient après est supprimé.

demandé 28-Nov par recher (354 points)

Juste pour tester, je vais écrire le caractère "26C4 snowman without snow (light snow)", suivi d'un "a" : ⛄ a

Juste pour tester, je vais écrire le caractère "1F301 foggy", suivi d'un "a" :

Juste pour tester, je vais écrire le caractère "U+263A White Smiling Face", suivi d'un "a" : ☺ a

Dernier test et après j'arrête de vous embêter. Le caractère "1F60A emoji qui sourit" (c'est pas le même qu'avant). Suivi d'un "a" :

1 Réponse

+2 votes

Il faut un encoding particulier utf8mb4

répondu 29-Nov par foxmask (2,702 points)

Je plussoie, le utf8 de MySQL n'est pas complet, seuls les caractères de 3 bytes et moins sont supportés. Pour le support complet (4 bytes), voir utf8mb4 ou un autre encodage (utf16 ou utf32, plus gourmands en mémoire).

Plus de détails ici.

Merci pour la réponse. Ça m'a avancé un peu, mais j'en suis pas encore au bout.

J'ai suivi les directives indiquées ici :
https://stackoverflow.com/a/24487309/6241709

J'ai fait le "ALTER TABLE" indiqué, mais pas le "ALTER DATABASE". Je dois avouer que ça me fait un peu peur de changer d'un coup le character_set de toute une db.

Du coup, j'ai ceci :

Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 119
Server version: 5.5.58-0+deb7u1 (Debian)

mysql> SHOW VARIABLES LIKE 'character_set%';
+--------------------------+----------------------------+
| Variable_name            | Value                      |
+--------------------------+----------------------------+
| character_set_client     | utf8mb4                    |
| character_set_connection | utf8mb4                    |
| character_set_database   | utf8                       |
| character_set_filesystem | binary                     |
| character_set_results    | utf8mb4                    |
| character_set_server     | utf8mb4                    |
| character_set_system     | utf8                       |
| character_sets_dir       | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+
8 rows in set (0.00 sec)

mysql> SHOW VARIABLES LIKE 'collation%';
+----------------------+--------------------+
| Variable_name        | Value              |
+----------------------+--------------------+
| collation_connection | utf8mb4_general_ci |
| collation_database   | utf8_general_ci    |
| collation_server     | utf8mb4_unicode_ci |
+----------------------+--------------------+
3 rows in set (0.00 sec)

mysql> desc appzor_truc;
+---------------+--------------+------+-----+---------+----------------+
| Field         | Type         | Null | Key | Default | Extra          |
+---------------+--------------+------+-----+---------+----------------+
| id            | int(11)      | NO   | PRI | NULL    | auto_increment |
| sujet         | varchar(100) | NO   |     | NULL    |                |
| message       | longtext     | NO   |     | NULL    |                |
| auteur        | varchar(80)  | NO   |     | NULL    |                |
| date          | datetime     | NO   |     | NULL    |                |
| important     | tinyint(1)   | NO   |     | NULL    |                |
| resume_alerte | varchar(140) | NO   |     | NULL    |                |
| lien          | varchar(200) | NO   |     | NULL    |                |
| image         | varchar(100) | NO   |     | NULL    |                |
| fichier       | varchar(100) | NO   |     | NULL    |                |
| mail          | tinyint(1)   | NO   |     | NULL    |                |
+---------------+--------------+------+-----+---------+----------------+
11 rows in set (0.00 sec)

mysql> SELECT CCSA.character_set_name FROM information_schema.`TABLES` T, information_schema.`COLLATION_CHARACTER_SET_APPLICABILITY` CCSA WHERE CCSA.collation_name = T.table_collation AND T.table_name = "appzor_truc";
+--------------------+
| character_set_name |
+--------------------+
| utf8mb4            |
+--------------------+
1 row in set (0.00 sec)

mysql> SELECT character_set_name, column_name FROM information_schema.`COLUMNS` WHERE table_name = 'appzor_truc';
+--------------------+---------------+
| character_set_name | column_name   |
+--------------------+---------------+
| NULL               | id            |
| utf8mb4            | sujet         |
| utf8mb4            | message       |
| utf8mb4            | auteur        |
| NULL               | date          |
| NULL               | important     |
| utf8mb4            | resume_alerte |
| utf8mb4            | lien          |
| utf8mb4            | image         |
| utf8mb4            | fichier       |
| NULL               | mail          |
+--------------------+---------------+
11 rows in set (0.00 sec)

Ensuite, j'ai redémarré mon serveur django. Et j'ai essayé de mettre un caractère unicode "1F301 foggy" le champ "message" de cette table, via l'interface d'admin de django.

C'est un peu mieux qu'avant, puisque cette fois-ci, le texte n'a pas été coupé. Mais le caractère a été remplacé par des points d'interrogations.

Et les logs du serveur indiquent ceci :

[07/Dec/2017 13:39:25] "GET /admin/jsi18n/ HTTP/1.1" 200 7030
/usr/local/lib/python3.4/site-packages/django/db/backends/mysql/base.py:112: Warning: Incorrect string value: '\xF0\x9F\x8C\x81\x0D\x0A...' for column 'message' at row 1
  return self.cursor.execute(query, args)

[07/Dec/2017 13:39:51] "POST /admin/appzor/truc/55/change/ HTTP/1.1" 302 0

Je n'ai pas d'autres messages d'erreur lorsque je réaffiche le contenu de la donnée. Je suppose que "le mal est fait", et que le remplacement par des points d'interrogation a été effectué au moment de l'écriture en base.

Est-ce que c'est l'interface d'admin django qui va pas bien, ou il faut que j'alter ma database, ou totalement autre chose ?

Il faut faire des backup à chaque étape
Sinon un rappel sur encode decode
http://sametmax.com/lencoding-en-python-une-bonne-fois-pour-toute/

Tu devrais vérifier que ta connexion à MySQL est elle aussi au bon encodage. Check les options que tu passes à MySQLdb, et aussi que tu disposes bien d'une version à jour (https://code.djangoproject.com/ticket/18392#comment:12).

...