2016-02-11 1 views
3

J'ai ces modèles.Empêcher Django en cascade supprimer à la superclasse

# models.py 
class A(models.Model): 
    name = models.CharField('Name', max_length=50) 

class B(A): 
    a_ptr = models.OneToOneField('A', primary_key=True, editable=True, parent_link=True) 
    number = models.CharField('Number', max_length=15) 

La relation que je suis en train de capturer est que chaque B est aussi un A, mais un A est pas nécessairement un B. Je pourrais utiliser un ForeignKey à la place, mais je préfère faire référence aux champs hérités de B, tel que B.name. La façon dont j'ai l'intention d'utiliser ces modèles est que A sera toujours instancié en premier. Et chaque fois qu'un B est instancié, il devra choisir un B existant (mais pas déjà pris).

Cela fonctionne assez bien jusqu'à présent, mais le seul problème que j'ai est avec les suppressions en cascade. Avec cette configuration, la suppression d'un B supprimera son A correspondant (ou du moins c'est ce qui se passe dans l'admin de django). Comment pourrais-je désactiver cette cascade?

Je suis conscient de l'attribut on_delete, mais si je l'ai défini, disons DO_NOTHING sur le champ a_ptr, cela aura pour effet de permettre à B d'exister sans A correspondant plutôt que l'inverse.

Comment est-ce que je peux faire ceci?

+0

[Cette réponse] (http://stackoverflow.com/questions/3711191/django-deleting-object-keeping-parent) est assez astucieuse (basculez 'b.a_ptr' pour pointer vers une instance différente avant de la supprimer). Je ne sais pas s'il y a une manière moins hacky. – Alasdair

Répondre

1

Vous pouvez réellement passer keep_parents=True à la méthode de suppression sur votre modèle.

a = A.objects.create(name='a') 
b = B.objects.create(a_ptr=a, number='1') 

b.delete(keep_parents=True) 
assert A.objects.filter(pk=a.pk).exists() 

Note: le paramètre keep_parents a été ajouté dans Django 1.9. Vous devrez probablement utiliser this answer pour les anciennes versions de Django.

+0

Ni l'un ni l'autre ne prend en charge les suppressions groupées, est-ce correct? – Khodeir

+0

La méthode 'delete' correcte sur QuerySets ne prend aucun paramètre. Si vous devez absolument supprimer en bloc, vous pouvez utiliser '_raw_delete' - par exemple. 'B.objects.all() ._ raw_delete (B.objects.db)' - mais ce n'est pas une API officielle et peut changer à tout moment. Il n'enverra également aucun signal, et il n'y a aucune protection pour les cascades. –