Django: Comment créer une relation entre 2 classes qui porte des attributs sans créer une troisèmes classes (through) ?

0 votes

J'ai une classe du type:

class Synergy(BaseModel):
    [../..]
    compounds = models.ManyToManyField(EssentialOil, through='SynergyCompound')
    [../..]

Qui pour une relation ManyToMany vers la classe "EssentialOil" mais avec des attributs propre à cette relation. J'ai donc créé une table intermediaire:

class SynergyCompound(BaseModel):
   essential_oil = models.ForeignKey(EssentialOil, on_delete=models.CASCADE, default=None)
   synergy = models.ForeignKey(Synergy, on_delete=models.CASCADE)
   quantity = models.DecimalField(verbose_name=_('quantity'), decimal_places=2, max_digits=4, default=None, null=False,
                               blank=False, validators=[MinValueValidator(Decimal('0.01'))])

En fait il n'y a qu'un seul attribut : quantity !

Je trouve cette approche null car elle conduit à la création d'une table supplémentaire et à des jointure qui seront inutiles.

Quelle approche pourrais-je utiliser pour conserver la valeur "quantity" propre à la relation entre EssentialOil et Synergy sans recourir à cette classe intermédiaire ?

demandé 18-Oct-2019 par iopsthecloud (160 points)

1 Réponse

0 votes

En fait, c'est une question de cardinalité dans ton analyse de base de données.
Tu peux jetter un œil à MERISE, ça date un peu mais ça reste assez pertinent...

https://ineumann.developpez.com/tutoriels/merise/initiation-merise/

Pour stocker une relation m2m, avec le modèle relationnel, il faut une table de relation entre les 2 clés primaires, pour dire "[Synergy Foo ] <=> [EssentialOil.Bar]" et "en même temps"
"[Synergy Foo] <=> [EssentialOil.Baz]"

Django crée donc une table, et c'est ce qui est souhaité : c'est la seule façon dans un SGBDR de stocker ce type de relation.

La table créé n'a que les champs essentiloil_id et synergy_id, et le couple est une PK...

Quand tu ajoutes un attribut à la relation, tu passes par le through et tu dois créer la table explicitement.

répondu 19-Oct-2019 par frague (692 points)

Sachant que je suis dans une relation 0n--0n je ne peux pas le coupler à un PK justement :(

En refomulant ma question, existe-il un moyen pythonique (ou django) pour gérer ce cas où l’attribut porté par la relation m2m n'a absolument pas besoin d'être dans une SGDBR car c'est un élément secondaire.

...