Classes de base abstraites vers héritage multi-tables

Comment faire la migration ?

a marqué ce sujet comme résolu.

Bonjour à tous,

Je dispose d’un site sur Django tournant depuis quelques années, et les modèles ont évolué (comprendre grossi) au fur et à mesure.

Ce site gère des tournois, de trois sortes (individuel, en équipe, et en 2v2). Ils sont représentés par quatres modèles : Tournament (modèle abstrait), SoloTournament, SideBySideTournament, TeamTournament, qui héritent tous de la classe abstraite et sont eux des modèles concrets.

J’ai donc trois tables distinctes en BDD.

Sauf qu’aujourd’hui, je me rends compte qu’il serait mieux d’avoir une classe concrète Tournament qui regrouperait toutes les informations communes. Cela me permettrait aussi de regrouper de manière visuelles les trois types de tournois (pour l’instant, par exemple, impossible de filtrer/trier sur les trois classes d’un coup).

Mon problème pour faire cela est double (malheureusement, il ne s’agit pas simplement d’enlever abstract = True) :

  • Comment migrer les anciens modèles vers les nouveaux (pas besoin de conserver les clés primaires, j’ai des slugs qui sont pour le coup uniques d’un modèle à l’autre) ?
  • Ces modèles ont des entités liées en ManyToOne, comment faire pour conserver les relations aussi ?

La réponse me semble être "prends ton courage à deux mains et écris les migrations" (ce qui me semble en effet une tâche longue et complexe), mais peut-être y a-t-il des solutions plus simples, c’est pourquoi je me tourne vers vous :)

Merci !

Salut,

Je ne connais que très peu Django mais je vais essayer de répondre car je pense que ta question est relativement générique.

Si j’ai bien compris, en base de données, tu as actuellement 3 tables (1 par type de tournoi) mais dans chacune de ces tables, tu as des colonnes communes (tournamentName par exemple). Ton nouveau modèle serait composé de 4 tables : 1 table Tournament qui comprendrait les colonnes communes (notamment tournamentName) puis 1 table par type de tournoi pour les données spécifiques à ce type de tournoi. Correct?

Si c’est bien le cas, je pense que ta migration peut se faire relativement facilement et sans même avoir de down time. Tu peux créer ta nouvelle table Tournament et ton application peut commencer à écrire dedans. À ce stade, ton application devra soit écrire les données communes (tournamentName et autres) dans la table Tournament et dans les tables spécifiques, soit lors de la lecture, lire à la fois dans Tournament et dans les tables spécifiques.

Maintenant que ta table est créée, tu peux passer à la migration. Je pense qu’un simple INSERT INTO Tournament (tournamentName, ...) SELECT tournamentName, ... from SoloTournament à répéter pour chaque table spécifiques devrait faire l’affaire. Une fois que c’est fait, tu peux supprimer les colonnes communes de tes tables spécifiques.

La dernière étape est de modifier ton application pour arrêter le comportement mentionné plus haut (écriture des données communes dans Tournament et les tables spécifiques ou lecture dans les deux tables). Celui-ci n’est plus nécessaire après migration: les données communes doivent uniquement être écrites dans la table Tournament et être lue dans cette table également.

+1 -0

Bonjour,

Je ne connais pas du tout Django, mais il s’agit d’un problème d’architecture assez général qui se poserait pratiquement à l’identique avec SpringBoot, ruby onr ails et d’autres.

Si tu n’as pas de conflit de clé primaire, c’est déjà pas mal. Tu pourras facilement faire un script qui déplace les données, comme par exemple:

insert into tournaments (id, name)
select id, name from side_by_side_tournaments;
insert into tournaments (id, name)
select id, name from individual_tournaments;
dalter table side_by_side_tournaments drop column name;
dalter table individual_tournaments drop column name;

Par contre, tu parles de vouloir manipuler les données de plusieurs types de tournoi à la fois, notamment pour faire du tri. Dans ce cas, ça pourrait être intéressant de passer au mode single table.

L’avantage du mode single table, c’est que toutes les données sont dans la même table, et donc les requêtes sont plus simples car tu économises des jointures.

L’inconvénient est la présences de colonnes contenant des null, ce qui peut éventuellement consommer un peu plus d’espace disque, et ce qui te ferme certaines opportunités de valider les données au niveau base de donnée (car tu ne peux pas ajouter de contrainte not null sur les colonnes spécifiques notamment). Pour un projet perso c’est pas trop gênant, mais ça l’est beaucoup plus dans les applications d’entreprise complexes, notamment quand plusieurs processus et/ou des humains accèdent aux mêmes données sans passer par l’application.

+0 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

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