Projet

Général

Profil

Development #42312

Pouvoir utiliser le JSONField de postgres

Ajouté par Valentin Deniaud il y a presque 4 ans. Mis à jour il y a presque 4 ans.

Statut:
Fermé
Priorité:
Normal
Assigné à:
Version cible:
-
Début:
30 avril 2020
Echéance:
% réalisé:

0%

Temps estimé:
Patch proposed:
Oui
Planning:
Non

Description

Dans #42008, on se rend compte que ce n'est pas possible car django-jsonfield < 1.3 est buggé et empêche d'utiliser les deux en parallèle.

Les tests passent avec la dernière version de django-jsonfield, mais les paquets debian sont plutôt autour de la version 1.1.

Alternativement, virer la dépendance avec django-jsonfield et tout faire avec postgres.

Ça a été fait dans a2, #29193, mais il y avait volonté de supporter sqlite, donc sans cette contrainte peut-être qu'il y a plus simple que ce qui est dit dans le ticket.


Fichiers

Révisions associées

Révision 5e1c910f (diff)
Ajouté par Valentin Deniaud il y a presque 4 ans

misc: use postgres JSONField (#42312)

Révision 0c5cad22 (diff)
Ajouté par Valentin Deniaud il y a presque 4 ans

misc: add missed migrations (#42312)

Révision 9ef99310 (diff)
Ajouté par Valentin Deniaud il y a presque 4 ans

misc: add migration to ensure jsonb type (#42312)

Historique

#1

Mis à jour par Valentin Deniaud il y a presque 4 ans

À la suite du début des discussions dans #42008,

Frédéric Péters a écrit :

Il me semble qu'on ne fait vraiment rien de particulier, qu'il n'y aurait même pas besoin de migration (juste traffiquer une précédente pour faire croire qu'on a depuis toujours utiliser le jsonfield de django.contrib.postgres).

Il y a effectivement pas grand chose à faire, mais au moins un ALTER TABLE, pour changer le type de la colonne de json à jsonb.

Une manière de faire déjà un peu lourde est présentée ici https://tech.polyconseil.fr/migrating-from-json-to-jsonb.html.

#2

Mis à jour par Frédéric Péters il y a presque 4 ans

Mais, c'est déjà jsonb : (j'ai regardé la prod, et chez moi) (?)

                     Table « passerelle_xxx.opengis_featurecache »
 Colonne  |          Type           |                             Modificateurs                             
----------+-------------------------+-----------------------------------------------------------------------
 id       | integer                 | non NULL Par défaut, nextval('opengis_featurecache_id_seq'::regclass)
 lat      | double precision        | non NULL
 lon      | double precision        | non NULL
 data     | jsonb                   | non NULL
 query_id | integer                 | non NULL
 text     | character varying(2048) | non NULL
#3

Mis à jour par Valentin Deniaud il y a presque 4 ans

OK, je comprends pas le pourquoi du comment, peut-être que Benj en saura plus.

#4

Mis à jour par Lauréline Guérin il y a presque 4 ans

dans django-jsonfield:

    def db_type(self, connection):
        if connection.vendor == 'postgresql':
            # Only do jsonb if in pg 9.4+
            if connection.pg_version >= 90400:
                return 'jsonb'
            return 'text'

Heureusement qu'on n'a pas du text en prod :)

#5

Mis à jour par Valentin Deniaud il y a presque 4 ans

  • Assigné à mis à Valentin Deniaud
#6

Mis à jour par Valentin Deniaud il y a presque 4 ans

Bien vu ! Donc la seule chose qui va casser, c'est quand on essaiera de créer un objet sans remplir le JSONField, parce que django-jsonfield posait dynamiquement un default=dict. Il y a deux endroits qui ont été identifiés dans les tests et que j'ai corrigés, mais sûrement qu'il y en a d'autre.

Et bien sûr, si il existe une prod datant d'avant postgres 9.4 ça va exploser en mille morceau, mais peut-être que c'est imaginable de corriger à la main/faire tourner un script dans ces cas là.

#7

Mis à jour par Frédéric Péters il y a presque 4 ans

Et bien sûr, si il existe une prod datant d'avant postgres 9.4 ça va exploser en mille morceau, mais peut-être que c'est imaginable de corriger à la main/faire tourner un script dans ces cas là.

On peut imaginer une migration qui assure que c'est déjà jsonb, qui fasse le changement sinon ? Parce que ça va arriver et c'est quand même bien plus facilement gérable partout si c'est géré via une migration.

   Table « passerelle_vincennes_entrouvert_com.csvdatasource_csvdatasource »
     Colonne      |          Type          |        Modificateurs                                                   
------------------+------------------------+------------------------------
 id               | integer                | non NULL Par défaut, ...
 title            | character varying(50)  | non NULL
 slug             | character varying(50)  | non NULL
 description      | text                   | non NULL
 csv_file         | character varying(100) | non NULL
 columns_keynames | character varying(256) | non NULL
 skip_header      | boolean                | non NULL
 _dialect_options | text                   |                   <-----------------
 sheet_name       | character varying(150) | non NULL
#8

Mis à jour par Valentin Deniaud il y a presque 4 ans

Frédéric Péters a écrit :

On peut imaginer une migration qui assure que c'est déjà jsonb, qui fasse le changement sinon ? Parce que ça va arriver et c'est quand même bien plus facilement gérable partout si c'est géré via une migration.

Oui donc on retombe tout à fait sur la méthode du billet de blog cité plus haut, sauf qu'on s'autorise de changer le code et la db en même temps.

Tu écris une migration donc pour être sûr que je ne me lance pas sur une fausse piste, on parle d'écrire à la mano une dizaine de fichiers de migrations, soit un par app qui utilise un jsonfield, à base de RunSQL ?

#9

Mis à jour par Frédéric Péters il y a presque 4 ans

Tu écris une migration donc pour être sûr que je ne me lance pas sur une fausse piste, on parle d'écrire à la mano une dizaine de fichiers de migrations, soit un par app qui utilise un jsonfield, à base de RunSQL ?

Oui; en modérant le côté "une dizaine de fichiers", genre en créant notre propre classe de EnsureJsonbType(Operation), pour tout à fait réduire la duplication, genre ces migrations seraient juste :

    operations = [
          EnsureJsonbType(model_name='csvdatasource', field_name='_dialect_options'),
    ]
#11

Mis à jour par Frédéric Péters il y a presque 4 ans

Si ça te semble possible, oui un test pour la migration de passerelle/utils/db.py ce serait super, mais si c'est galère parce que ça oblige à sortir de l'ORM pour traffiquer la DB, on peut juste être très attentif en relisant...

(mais il faut ajouter l'entête de licence au fichier)

#12

Mis à jour par Valentin Deniaud il y a presque 4 ans

Voilà un test, c'était pas si horrible, juste un petit peu.

Pas besoin de tester toutes les migrations je pense, le migrate exécuté de toute façon par les tests garanti normalement l'absence de faute de frappe sur le nom des tables/colonnes.

#13

Mis à jour par Frédéric Péters il y a presque 4 ans

reversible = False

Je mettrais True, et un backwards qui ne fait rien vu que ça vivait déjà très bien en jsonb; non ?

#15

Mis à jour par Frédéric Péters il y a presque 4 ans

  • Statut changé de Solution proposée à Solution validée
#16

Mis à jour par Valentin Deniaud il y a presque 4 ans

  • Statut changé de Solution validée à Résolu (à déployer)
commit 9ef993108b945a41d2f9d430c6820c6c90cae6b0
Author: Valentin Deniaud <vdeniaud@entrouvert.com>
Date:   Mon May 4 14:04:32 2020 +0200

    misc: add migration to ensure jsonb type (#42312)

commit 0c5cad2296914a9d2a4865accd391eed507fdb55
Author: Valentin Deniaud <vdeniaud@entrouvert.com>
Date:   Mon May 4 14:03:41 2020 +0200

    misc: add missed migrations (#42312)

commit 5e1c910fbfacb15dd37ea8f0192561dcc15054bc
Author: Valentin Deniaud <vdeniaud@entrouvert.com>
Date:   Thu Apr 30 12:00:34 2020 +0200

    misc: use postgres JSONField (#42312)
#17

Mis à jour par Frédéric Péters il y a presque 4 ans

  • Statut changé de Résolu (à déployer) à Solution déployée

Formats disponibles : Atom PDF