Question à propos de "OneToOne" et de "on_delete"

a marqué ce sujet comme résolu.

Bonjour, je possède deux tables Company et BankAccount:

class BankAccount(models.Model):
    name = models.CharField(max_length=50)
    iban = models.CharField(max_length=27)
    bic = models.CharField(max_length=8)
                
class Company(CommonInfo):
    name = models.CharField(max_length=50)
    siren = models.PositiveBigIntegerField()
    vat = models.BooleanField(default=False)

…et je souhaiterais lier ces-dernières par une relation de type OneToOne :

class BankAccount(models.Model):
    name = models.CharField(max_length=50)
    iban = models.CharField(max_length=27)
    bic = models.CharField(max_length=8)
                
class Company(CommonInfo):
    name = models.CharField(max_length=50)
    siren = models.PositiveBigIntegerField()
    vat = models.BooleanField(default=False)
    bank_account = models.OneToOneField(BankAccount, on_delete=models.CASCADE)

Selon moi, il est plus logique d’associer une entreprise à un compte bancaire plutôt qu’un compte bancaire à une entreprise. Or, dans le code ci-dessus : si le compte bancaire associé à l’entreprise est supprimé, l’entreprise sera-elle également supprimé ?

Deuxième question : cette relation est-elle bidirectionnelle ? Je voudrais pouvoir accéder à l’entreprise depuis son compte bancaire et inversement.

Merci d’avance.

+0 -0

Hello,

Tout dépend de ton cas d’usage : le compte appartient à (ou contrôle) l’entreprise où l’entreprise appartient (ou contrôle) au compte ?

Est-ce qu’une entreprise peut avoir plusieurs comptes ?

La cascade se fait dans un seul, du moins sens en SQL : la table qui contient la clé étrangère peut supprimer dans la table liée, l’inverse devra être géré par ton code applicatif.

Au-delà de Django, il s’agit ici plus de modélisation de données que de Python ou d’un ORM.

Hello,

Tout dépend de ton cas d’usage : le compte appartient à l’entreprise où l’entreprise appartient au compte ?

Est-ce qu’une entreprise peut avoir plusieurs comptes ?

La cascade se fait dans un seul, du moins sens en SQL : la table qui contient la clé étrangère peut supprimer dans la table liée, l’inverse devra être géré par ton code applicatif.

Au-delà de Django, il s’agit ici plus de modélisation de données que de Python ou d’un ORM.

viki53

Merci pour ta réponse. Permets-moi de détailler un peu plus :

Le compte appartient à l’entreprise. Dans le formulaire de création d’une entreprise, il y a la possibilité d’ajouter le compte associé. Si l’entreprise en question est supprimée, alors le compte associé doit l’être également. En revanche, si le compte est supprimé, il serait catastrophique que l’entreprise associée soit supprimée…

Ensuite, une entreprise ne peut avoir qu’un seul compte, d’où la relation OneToOne.

Au-delà de Django, il s’agit ici plus de modélisation de données que de Python ou d’un ORM.

En fait je voulais savoir où placer le on_delete. La doc de Django indique :

ForeignKey.on_delete : When an object referenced by a ForeignKey is deleted, Django will emulate the behavior of the SQL constraint specified by the on_delete argument.

Donc dans mon code ci-dessus, l’objet référencé par ForeignKey est BankAccount, donc si ce-dernier est supprimé, alors l’entreprise associée également puisque on_delete=CASCADE ?

+0 -0

En fait je voulais savoir où placer le on_delete. La doc de Django indique :

ForeignKey.on_delete : When an object referenced by a ForeignKey is deleted, Django will emulate the behavior of the SQL constraint specified by the on_delete argument.

Donc dans mon code ci-dessus, l’objet référencé par ForeignKey est BankAccount, donc si ce-dernier est supprimé, alors l’entreprise associée également puisque on_delete=CASCADE ?

Big-Blob

C’est bien ça.

À mon avis, ce serait plus logique que ce soit le compte qui référence l’entreprise, puisque c’est le compte qui appartient à l’entreprise. Et effectivement dans ce sens-là (que je te propose), le on_delete supprimera le compte bancaire associé.

+1 -0

En fait je voulais savoir où placer le on_delete. La doc de Django indique :

ForeignKey.on_delete : When an object referenced by a ForeignKey is deleted, Django will emulate the behavior of the SQL constraint specified by the on_delete argument.

Donc dans mon code ci-dessus, l’objet référencé par ForeignKey est BankAccount, donc si ce-dernier est supprimé, alors l’entreprise associée également puisque on_delete=CASCADE ?

Big-Blob

C’est bien ça.

À mon avis, ce serait plus logique que ce soit le compte qui référence l’entreprise, puisque c’est le compte qui appartient à l’entreprise. Et effectivement dans ce sens-là (que je te propose), le on_delete supprimera le compte bancaire associé.

Moté

En effet, après reflexion ! En revanche, imaginons la situation suivante :

Je possède une table User qui enregistre tous les utilisateurs du site. Eux aussi possèdent un compte bancaire. Logiquement, je devrais avoir ça :

class BankAccount(models.Model):
    name = models.CharField(max_length=50)
    iban = models.CharField(max_length=27)
    bic = models.CharField(max_length=8)
    company = models.OneToOneField(Company, on_delete=models.CASCADE)
    user = models.OneToOneField(User, on_delete=models.CASCADE)

Or, soit un compte appartient à une entreprise, soit il appartient à un utilisateur, mais pas les deux… Je me demande si je peux contourner le problème ainsi :

user = models.OneToOneField(User, on_delete=models.CASCADE, default=None)

Je pense avoir trouvé une solution au problème exposé ci-dessus grâce à CheckConstraint :

class BankAccount(models.Model):
    name = models.CharField(max_length=50)
    iban = models.CharField(max_length=27, unique=True)
    bic = models.CharField(max_length=8, unique=True)
    company = models.OneToOneField(
        Company, on_delete=models.CASCADE, blank=True, null=True)
    user = models.OneToOneField(
        User, on_delete=models.CASCADE, blank=True, null=True)

    class Meta:
        constraints = [
            models.CheckConstraint(
                check=Q(company__isnull=False, user=None) | Q(
                    user__isnull=False, company=None),
                name='not_both_null_or_true'
            )
        ]

Pt’ite question malgré tout, trouvez-vous le formattage bizarre dans le code-ci dessus ? C’est auto-pep8 qui s’en occupe.

+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