DB schema / composition de models dans Django

Bonjour,

Je suis en train de me demander comment construire mon data model avec Django pour représenter une structure / bâtiment avec plein de composants (poutres, équipements, chacun représenté par un model Django) qui peuvent se composer de différentes manières selon mes projets. Je ne veux donc pas créer un foreignkey de mon poutre vers le building parent car son ‘parent’ pourrait être plutôt une column ou un wall ou …

J’aimerais par la suite pouvoir trouver le parent de mon objet et aussi trouver rapidement l’ensemble des enfants d’un parent.

Quelqu’un aura un retour d’expérience / des conseils pour ce type de situation? Me faut-il une structure séparée de graph (DAG) pour définir et modifier ces relations ? Comment constuire un tel DAG?

Merci,

-Graham

Il va falloir nous en dire plus sur les contraintes de ton modèle si tu souhaites que l’on t’aide.

Par exemple, est-ce l’ordre des composants est important ? Si non, dans ce cas tu peux faire un modèle Component générique et mettre un M2M vers ce modèle dans Building.

Est-ce que tu as besoin d’associer plusieurs fois le même composant ? Dans ce cas, il faudra peut être utiliser une relation M2M avec un modèle intermédiaire (through).

Bref, l’idée c’est que tu dresses une petite cartographie rapide de la façon dont tu aimerais organiser les choses, et en faisant cet exercice il est possible que tu répondes toi même à cette question.

1 « J'aime »

De loin comme ça, j’aurai envie d’essayer de commencer avec un seul modèle (disons “Thing”), avec comme dit @debnet une many2many, mais sur elle même (éventuellement via une seconde table (through) pour y stocker une description de cette relation).

Ensuite tu pourrais rajouter des one2one liées à Thing pour y ajouter des données spécifiques quand c’est nécessaire.

Regarde le modèle de donnée d’OSM aussi si ça peut t’inspirer, ils n’ont pas grand chose, pour caricaturer ils ont juste :

  • Des points, qui peuvent avoir des attributs (libres, ce sont des paires de clef-valeur)
  • Des chemins orientés entre des points, qui peuvent avoir des attributs aussi.

Une maison rectangulaire c’est alors quatre points reliés entre eux par un seul chemin (fermé).

Une route c’est alors plein de points reliés entre eux par un seul chemin (ouvert).

Ensuite tout se joue sur les attributs libres qu’ils y collent, comme “building=ruins”, ou “amenity=parking”.

Et ça suffit pour cartographier le monde (bon ils ont aussi des “relations”).

1 « J'aime »

Merci @debnet et @mdk, je débute a la fois en Django et en design de schéma alors c’est clair que je ne connais pas encore toutes les bonnes questions á me poser

Bonne question - j’ai parfois besoin de trier une liste de composants selon une logique specifique au composant. Il y a une hierarchie naturelle dans les composants mais cette hierarchie pourrait évoluer dans le futur (peut-etre).

Oui très certainement

Ce qui est sur aussi est que je dois prendre en compte l’absence de certains éléments dans ma hiérarchie donc le même appli devrait tenir compte des cas suivants:

image

image

J’ai l’impression que je ne peux pas (ou ne devrait pas) paramétrer mes relations par exemple avec un CharField qui donne le nom des modèles qui sont lies (principe de normalisation / atomic columns… ou j’ai mal compris ?) donc il faut que j’anticipe aujourd’hui les relations probables pour chaque composant et que je définie un many to many field pour chaque relation probable, quitte a rajouter ou modifier mes modeles demain si je dois changer les relations, ce qui veut dire changer plusieurs modèles, dont Site pour chaque changement de relation… Dans le cas ci-dessus Beam aurait des manytomany avec null=True vers Tower, Floor, Beam et Equipment

Je vais regarder du plus pres les through

Avec ma réponse, et ton schema, tu aurais :

Thing qui fait une seule manytomany avec Thing, puis, au besoin d’ajouter des attributs pour chaque type spécifique :

  • Site lié à Thing en onetoone
  • Building lié à Thing en onetoone
  • Floor lié à thing en onetoone
  • Equipement lié à Thing en onetoone

Ou àla OSM : Attribute lié à Thing en onetomany : une « chose » a plusieurs « attributs », Attribute ayant juste « key, value », qui t’évite tout plein de onetomany, et aussi qui t’évite un alter table a chaque ajout de type (mais qui doit avoir un coup caché ailleurs :D)

C’est chiant et monotone (donc sans surprises).

Et tu peux tasser probablement plein d’informations dans Thing : tout ce qui est commun à Site, Building, Floor, Equipement, etc…

1 « J'aime »

J’dirais No-SQL, un modèle relationnel semble peu adapté, juste comme ça en passant.
Design Schema for NoSQL Data Models
Djongo pour Django :slight_smile: par exemple: Djongo - Code Source - | Djongo - Documentation -

En passant, si quelqu’un se sent l’âme d’un hacker et a envie de faire quelques lignes sur son CV ou comme moi pour le plaisir, c’est maintenant qu’on se prépare pour: L’Atlas Hackathlon c’est l’occasion de placer du python là dedans.

1 « J'aime »

Je ne sais pas si je l’ai bien implémenté mais ca pourrait ressembler a ca (avec l’ajout d’un site) :? La méthode delete sur thingy me permet d’effacer le Building / Antenna avec son Thing et Thingy d’un coup sans remonter la chaine plus loin…

from django.db import models


class Thing(models.Model):
    name = models.CharField(max_length=128,
                            null=True)
    thing = models.ManyToManyField("Thing",
                                   related_name="related_thing",
                                   blank=True,
                                   )

    def __str__(self):
        return self.name


class Thingy(models.Model):
    thing = models.OneToOneField(to="Thing",
                                 on_delete=models.CASCADE,
                                 unique=True,
                                 null=True
                                 )

    def delete(self):
        self.thing.delete(keep_parents=False)

    def __str__(self):
        return self.thing.name


class Tower(Thingy):
    ...


class Building(Thingy):
    ...


class Antenna(Thingy):
    mounting = models.ForeignKey(to="Thing",
                              on_delete=models.PROTECT,
                              default=None,
                              blank=True,
                              null=True,
                              )



Regarde du côté des relations génériques, avec les content types.
Pour ton problème initial ça m’a l’air de bien fitter, et c’est pas très compliqué à mettre en place

https://docs.djangoproject.com/en/4.0/ref/contrib/contenttypes/#generic-relations

1 « J'aime »