Project

General

Profile

Développement #42312

Pouvoir utiliser le JSONField de postgres

Added by Valentin Deniaud over 4 years ago. Updated over 4 years ago.

Status:
Fermé
Priority:
Normal
Target version:
-
Start date:
30 April 2020
Due date:
% Done:

0%

Estimated time:
Patch proposed:
Yes
Planning:
No

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.


Files

Associated revisions

Revision 5e1c910f (diff)
Added by Valentin Deniaud over 4 years ago

misc: use postgres JSONField (#42312)

Revision 0c5cad22 (diff)
Added by Valentin Deniaud over 4 years ago

misc: add missed migrations (#42312)

Revision 9ef99310 (diff)
Added by Valentin Deniaud over 4 years ago

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

History

#1

Updated by Valentin Deniaud over 4 years ago

À 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

Updated by Frédéric Péters over 4 years ago

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

Updated by Valentin Deniaud over 4 years ago

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

#4

Updated by Lauréline Guérin over 4 years ago

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

Updated by Valentin Deniaud over 4 years ago

  • Assignee set to Valentin Deniaud
#6

Updated by Valentin Deniaud over 4 years ago

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

Updated by Frédéric Péters over 4 years ago

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

Updated by Valentin Deniaud over 4 years ago

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

Updated by Frédéric Péters over 4 years ago

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

Updated by Frédéric Péters over 4 years ago

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

Updated by Valentin Deniaud over 4 years ago

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

Updated by Frédéric Péters over 4 years ago

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

Updated by Frédéric Péters over 4 years ago

  • Status changed from Solution proposée to Solution validée
#16

Updated by Valentin Deniaud over 4 years ago

  • Status changed from Solution validée to 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

Updated by Frédéric Péters over 4 years ago

  • Status changed from Résolu (à déployer) to Solution déployée

Also available in: Atom PDF