IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Django Python Discussion :

Suppression en cascade


Sujet :

Django Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre très actif Avatar de keitaro_bzh
    Homme Profil pro
    Est-ce intéressant?
    Inscrit en
    Juin 2009
    Messages
    320
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Est-ce intéressant?

    Informations forums :
    Inscription : Juin 2009
    Messages : 320
    Par défaut Suppression en cascade
    Bonjour à tous,

    Je débute sur le développement python, et pour le moment, cela se passe pas trop mal.
    Cependant, je tombe face à un os dont je n'arrive pas à comprendre (l'autoformation a ses limites...)

    Je suis en train de développer une petite application web avec Django. J'ai une classe Personne qui est lié à une classe Coordonnées en relation OneToOnoeField

    extrait de mon models.py:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    class Personne(models.Model):
        nom = models.CharField(max_length=100)
        prenom = models.CharField(max_length=100, blank=True, null=True)
        coordonnees = models.OneToOneField(Coordonnees, on_delete=models.CASCADE, blank=True, null=True)
     
    class Coordonnees(models.Model):
        telephone = models.CharField(max_length=15, blank=True, null=True)
        mobile = models.CharField(max_length=15, blank=True, null=True)
    L'enregistrement des mes objets fonctionnent bien en base. La récupération également. Cependant, lorsque je veux supprimer une Personne, j'aimerai que les Coordonnées associées soient également supprimées. Or, cela ne fonctionne pas. Par contre, si je supprime les coordonnées de la personne, cela supprime ma personne dans la base.

    Extrait de mon views.py
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #@login_required(login_url='login')
    def personne_delete(request, id):
        personne = get_object_or_404(Personne, pk=id)
        try:
            # Cela supprime bien mes coordonnées et ma personne
            personne.coordonnees.delete()
            # Cela supprime uniquement ma personne, mais pas mes coordonnées associées
            personne.delete()
        except IntegrityError:
            personne.onArchive = True
            personne.save()
        return redirect('MyContacts:mycontacts_personnes_list')
    Je pense que j'ai pas compris un truc, dans le raisonnement python.
    Y'a-t-il quelqu'un pour éclairer ma faible lanterne?

    En vous remerciant par avance.

  2. #2
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 787
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 787
    Par défaut
    Salut,

    Citation Envoyé par keitaro_bzh Voir le message
    Je pense que j'ai pas compris un truc, dans le raisonnement python.
    Là tout de suite ce que vous regardez, c'est la relation entre 2 tables au sens SQL....
    Et côté SQL ça me semble cohérent.
    Ce qui est discutable par contre c'est d'avoir 2 tables alors qu'une seule suffirait.

    Et dans tout çà rien ne concerne vraiment Python ou Django.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  3. #3
    Membre très actif Avatar de keitaro_bzh
    Homme Profil pro
    Est-ce intéressant?
    Inscrit en
    Juin 2009
    Messages
    320
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Est-ce intéressant?

    Informations forums :
    Inscription : Juin 2009
    Messages : 320
    Par défaut
    Citation Envoyé par wiztricks Voir le message
    Ce qui est discutable par contre c'est d'avoir 2 tables alors qu'une seule suffirait.
    Et dans tout çà rien ne concerne vraiment Python ou Django.
    Merci pour votre réponse. A la lecture, je me suis posé la question...

    Mais après réflexion (en continuant mon appli) je me souviens pourquoi j'ai fait ça. Je vais avoir une classe Societe, qui va aussi avoir des coordonnées. Donc, au lieu d'avoir de recréer des champs téléphone, mobile, etc. pour chaque classe, je crée une classe que je rattache à mes classes société et personne (et cela se retranscrit de cette manière coté SQL).

    Ca m'évite aussi de modifier mes classes si je veux rajouter une info type email2.. je suis un peu fainéant sur les bords...

    Je ne sais pas si c'est une bonne pratique mais ça doit être mon coté infra qui me fait mutualiser au maximum.. :p

  4. #4
    Expert confirmé
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    4 172
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 4 172
    Par défaut
    Bonsoir,

    Je ne suis pas dans la tête de @wiztricks mais je dirai qu'on est d'accord... Je verrai bien cette manière de faire en prenant en compte la partie société (attention pas testé du tout)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    from django.db import models
     
    class Personne(models.Model):
        nom = models.CharField(max_length=100)
        prenom = models.CharField(max_length=100, blank=True, null=True)
     
     
    class Coordonnees(models.Model):
        telephone = models.CharField(max_length=15, blank=True, default="")
        mobile = models.CharField(max_length=15, blank=True, default="")
     
        class Meta:
            abstract = True
     
     
    class CoordonneesPerson(Coordonnees):
        personne = models.OneToOneField(Personne, on_delete=models.CASCADE)
     
    class CoordonneesSociety(Coordonnees):
        society = models.OneToOneField(Society, on_delete=models.CASCADE)
    Je pense que la suppression devrait mieux fonctionner, à tester !

  5. #5
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 787
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 787
    Par défaut
    Citation Envoyé par fred1599 Voir le message
    Je ne suis pas dans la tête de @wiztricks mais je dirai qu'on est d'accord...
    Si j'ai bien compris, le PO cherche à avoir X et Y qui partagent la même adresse (donc la PK va de l'entité vers l'adresse).

    Mais c'est compliqué: si je crée une adresse associée à X à l'instant t et que plus tard je crée Y comment je récupère l'adresse précédente pour aussi l'associer à Y? Et si on ne sait pas faire ça on va avoir autant d'adresses que de X et de Y (plein de doublons) et ce truc ne sert à rien (car on ne sait pas le faire marcher).


    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  6. #6
    Expert confirmé
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    4 172
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 4 172
    Par défaut
    Si j'ai bien compris, le PO cherche à avoir X et Y qui partagent la même adresse
    Le PO utilise un OneToOneField qui indique justement qu'une personne est liée à une seule adresse.

    Et donc on évite le partage de coordonnées, peut-être pour une personne titulaire de ... ou d'autres exemples et c'est ce OneToOneField qui empêche ce partage.

    Le OneToOneField empêche justement le doublon de coordonnées, qui est équivalent à une clé étrangère dont on y affecte une contrainte d'unicité.

    mais si tu as compris cela et moi autre chose, c'est que ça n'est certainement pas assez claire, et on doit mieux comprendre l'histoire raconté par le PO avec des détails supplémentaires.

    EDIT: Je suis par contre d'accord sur le fait que le OneToOneField est à mon sens, pas la bonne relation, mais on ne connaît pas la problématique métier, donc...

  7. #7
    Membre très actif Avatar de keitaro_bzh
    Homme Profil pro
    Est-ce intéressant?
    Inscrit en
    Juin 2009
    Messages
    320
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Est-ce intéressant?

    Informations forums :
    Inscription : Juin 2009
    Messages : 320
    Par défaut
    Bonjour à vous 2,

    Merci Fred1599, la solution proposée fonctionne à merveille. Cependant, j'ai une question con, mon modèle a désormais la forme suivante:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    class Coordonnees(models.Model):
        telephone = models.CharField(max_length=15, blank=True, null=True)
     
    class Personne(models.Model):
        nom = models.CharField(max_length=100)
        prenom = models.CharField(max_length=100, blank=True, null=True)
     
    class CoordonneesPersonne(Coordonnees):
        personne = models.OneToOneField(Personne, on_delete=models.CASCADE)
    L'enregistrement se fait donc via mon fichier view.py:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    if form.is_valid():
            personne.nom = form.cleaned_data['nom']
            personne.prenom = form.cleaned_data['prenom']
            personne.save()
     
            formCoordonnees = CoordonneesForm(request.POST)
            if formCoordonnees.is_valid():
                personneCoordonnees.telephone = formCoordonnees.cleaned_data['telephone']
                personneCoordonnees.personne = personne
                personneCoordonnees.save()
    Jusque la tout va bien. Par contre, ma question revient sur le chargement de mes coordonnées ou avant, je faisais cela par la ligne toujours dans mon fichier view.py
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    personnes = Personne.objects.all().order_by("nom")
    return render(request,'MyContacts/personnes.html',context)
    Mais du coup, mes coordonnesPersonne étant une autre classe, cela ne charge pas automatiquement le contenu de cette classe. J'imagine que je dois surcharger ma classe Personne, pour qu'au chargement, il aille vérifier la présence des coordonnées? Mais la, ça dépasse mon niveau actuel...


    Je profite pour poser 2 autres questions cons certainement.
    - Que voulez vous dire par PO? C'est une insulte envers le novice que je suis? lol
    - Dans l'exemple fourni, tu ajoutes pour quelle raison le code:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    class META
       abstract = True
    En lisant votre discussion, l'objectif n'est pas d'avoir des coordonnées uniques (quoique sur le principe, un seul numéro de téléphone n'est possible à la fois car il est unique). Donc, si je suis bien, il faut plutôt utilisé un ForeignKey? pourquoi l'utilisation du OneToOneFieldest? Simplement que celui me paraissait le plus approprié (je n'avais pas pris en compte la particularité de l'unicité) car une personne/societe ne peut avoir qu'une seule "coordonnée" dans la base SQL.
    Du coup, par curiosité, j'ai testé l'ajout d'un même numéro de téléphone, et malgré l'utilisation du OneToOneField, je peux ajouter le même numéro. Encore un truc qui m'échappe

  8. #8
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 787
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 787
    Par défaut
    Citation Envoyé par fred1599 Voir le message
    Le PO utilise un OneToOneField qui indique justement qu'une personne est liée à une seule adresse.
    Vu où il est placé, pas certain que le OneToOneField traduise l'intention. C'est plutôt une maladresse qui semble confirmée dans la réponse précédente.

    Citation Envoyé par keitaro_bzh
    - Que voulez vous dire par PO? C'est une insulte envers le novice que je suis? lol
    Un acronyme disant "Post Original .


    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  9. #9
    Expert confirmé
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    4 172
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 4 172
    Par défaut
    Peut-être...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    CoordonneesPerson.objects.order_by("personne__nom").values("personne__nom", "personne__prenom")
    À tester...

  10. #10
    Membre très actif Avatar de keitaro_bzh
    Homme Profil pro
    Est-ce intéressant?
    Inscrit en
    Juin 2009
    Messages
    320
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Est-ce intéressant?

    Informations forums :
    Inscription : Juin 2009
    Messages : 320
    Par défaut
    En m'inspirant de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    CoordonneesPerson.objects.order_by("personne__nom").values("personne__nom", "personne__prenom")
    j'ai écrit cette portion de code qui fonctionne dans mon view.py

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    personnes = Personne.objects.all().order_by("nom")
    personnesCoordonnees= CoordonneesPersonne.objects.all()
    context = {
        'personnes': personnes,
        'personnesCoordonnees': personnesCoordonnees,
    }
    return render(request,'MyContacts/personnes.html',context)
    Du coup, dans mon fichier MyContacts/personnes.html, j'ai le code ci-dessous
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    {% for personne in personnes %}
       <tr>
          <td>
              {{ personne.nom }} {% if personne.prenom != None %}{{ personne.prenom }}{% endif %}
          </td>
          <td>
             {% for personneCoordonnees in personnesCoordonnees %}
                {% if personneCoordonnees.personne.pk == personne.pk %}
                   {% if personneCoordonnees.telephone != None %}<p>{{ personneCoordonnees.telephone }}</p>{% endif %}
                {% endif %}
             {% endfor %}
         </td>
    </tr>
    {% endfor %}
    Les données s'affichent, la suppression en cascade aussi mais cela me parait loin d'être optimal, sachant que je boucle sur toutes les coordonnées pour récupérer la bonne...

  11. #11
    Expert confirmé
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    4 172
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 4 172
    Par défaut
    ça commence à devenir le cirque ton histoire, je propose après réflexion et tes besoins une autre forme, désolé, mais c'est au fur et à mesures de tes demandes que je vois d'autres possibilités...

    La surcharge de la méthode delete pourrait permettre de supprimer les coordonnées spécifiques à la personne. Il faut y réfléchir, un début de code à compléter selon tes besoins !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    from django.db import models
     
    class Person(models.Model):
        name = models.CharField(max_length=32, blank=False, null=False)
        firstname = models.CharField(max_length=32, blank=False, null=False)
        coordinate = models.ForeignKey("Coordinate", models.CASCADE, null=False)
     
        def delete(self, using=None, keep_parents=False):
            Coordinate.objects.get(pk=self.coordinate.pk).delete()
            super().delete()
     
     
    class Coordinate(models.Model):
        phone = models.CharField(max_length=10, unique=True, default="")
        mobile = models.CharField(max_length=10, unique=True, default="")
    En même temps je pense à l'idée de @wiztricks qui pourrait se rapprocher de ma solution ci-dessus... si tout le monde est ok, alors ça serait top !

  12. #12
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 787
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 787
    Par défaut
    Citation Envoyé par fred1599 Voir le message
    ça commence à devenir le cirque ton histoire
    Quand on explore sans trop savoir ce qu'on veut, ça devient vite le bazar... et toute solution traduira une cohérence de son auteur pas forcement très lisible lorsqu'on débute => montrer qu'on sait faire des choses avec django sera rassurant mais pas sur que ça aide.

    Citation Envoyé par fred1599 Voir le message
    En même temps je pense à l'idée de @wiztricks qui pourrait se rapprocher de ma solution ci-dessus
    Vu ce que sont les adresses autant utiliser le numéro de téléphone portable comme clé primaire.... mais ça me semble un peu léger comme "adresse".

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  13. #13
    Membre très actif Avatar de keitaro_bzh
    Homme Profil pro
    Est-ce intéressant?
    Inscrit en
    Juin 2009
    Messages
    320
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Est-ce intéressant?

    Informations forums :
    Inscription : Juin 2009
    Messages : 320
    Par défaut
    Citation Envoyé par fred1599 Voir le message
    Il faut y réfléchir, un début de code à compléter selon tes besoins !
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    from django.db import models
     
    class Person(models.Model):
        name = models.CharField(max_length=32, blank=False, null=False)
        firstname = models.CharField(max_length=32, blank=False, null=False)
        coordinate = models.ForeignKey("Coordinate", models.CASCADE, null=False)
     
        def delete(self, using=None, keep_parents=False):
            Coordinate.objects.get(pk=self.coordinate.pk).delete()
            super().delete()
     
     
    class Coordinate(models.Model):
        phone = models.CharField(max_length=10, unique=True, default="")
        mobile = models.CharField(max_length=10, unique=True, default="")
    Merci, c'est top. Ca fonctionne comme désiré. C'est plus propre et plus parlant que le code précédent.

    Citation Envoyé par fred1599 Voir le message
    ça commence à devenir le cirque ton histoire
    Désolé pour le manque de précisions, mais c'est clair dans ma tête. Mais je sais que la mienne marche à l'envers...
    Il y a milles façons de faire, mais l'utilisation d'un framework nous(enfin moi) remet dans le bon chemin de la programmation non? :p

    Merci à vous deux d'avoir pris le temps de me répondre en tout cas

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Suppression en cascade
    Par music03 dans le forum Installation
    Réponses: 1
    Dernier message: 29/07/2005, 20h47
  2. suppression en cascade dans formulaire et sous-formulaire
    Par tooneygirl dans le forum Access
    Réponses: 7
    Dernier message: 20/06/2005, 14h17
  3. Requetes de suppression en cascade
    Par log2n dans le forum Décisions SGBD
    Réponses: 1
    Dernier message: 20/05/2005, 10h07
  4. Suppression en cascade
    Par log2n dans le forum Langage SQL
    Réponses: 2
    Dernier message: 19/05/2005, 20h33
  5. [debutant]suppression en cascade
    Par christophebmx dans le forum MS SQL Server
    Réponses: 12
    Dernier message: 03/05/2005, 09h51

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo