2012-10-05 8 views
28

Ich habe folgendes Modell:OneToOneField und Löschen

from django.db import models 
from django.contrib.auth.models import User 


class Profile(models.Model): 
    user = models.OneToOneField(User) 
    # ... 

    def __unicode__(self): 
     return u'%s %s' % (self.user.first_name, self.user.last_name) 

Wenn das Admin Django mit dem Benutzer zu löschen, wird das Profil als auch gelöscht, das ist das, was ich will. Allerdings, wenn Sie den Django-Administrator verwenden, um das Profil zu löschen, wird der Benutzer nicht gelöscht, was ist nicht was ich will. Wie kann ich erreichen, dass das Löschen des Profils auch den Benutzer löscht?

Antwort

41

Da Profile Links zu User ist es das abhängige Modell in der Beziehung. Wenn Sie einen Benutzer löschen, löscht es daher alle abhängigen Modelle. Wenn Sie jedoch ein Profil löschen, wird es nicht entfernt, da User nicht vom Profil abhängt.

Leider nach on_delete Django docs, gibt es keine on_delete Regel, die die übergeordneten Beziehungen löscht. Um das zu tun, können Sie die Profile ‚s delete Methode überschreiben:

class Profile(models.Model): 
    # ... 

    def delete(self, *args, **kwargs): 
     self.user.delete() 
     return super(self.__class__, self).delete(*args, **kwargs) 

Dann, wenn dabei:

Profile.objects.get(...).delete() 

wird auch das Profil des Benutzers löschen. Doch die delete Methode wird nicht aufgerufen werden, wenn Profile mit querysets Löschen (das ist das, was in Django Admin genannt wird), da dann verwendet Django SQL DELETE Objekte in loser Schüttung löschen:

Profile.objects.filter(...).delete() 

In diesem Fall, wie von Django empfohlen docs, müssen Sie post_delete Signal (docs) verwenden.

from django.dispatch import receiver 
from django.db.models.signals import post_delete 

@receiver(post_delete, sender=Profile) 
def post_delete_user(sender, instance, *args, **kwargs): 
    if instance.user: # just in case user is not specified 
     instance.user.delete() 
+0

Vielen Dank! Ich bin immer noch neu in Django, also, falls andere Django-Noobs das finden sollten, musste ich dem @receiver-Dekorator eine dispatch_uid hinzufügen, damit es funktioniert. Aber danach hat es super geklappt! – Nick

7

Verwenden Sie ein Signal auf den Profile ‚s Löschmethode zu gehen und löschen Sie die zugehörigen Benutzer:

from django.db.models.signals import post_delete 

def delete_related_user(sender, **kwargs): 
    deleted_profile = kwargs['instance'] 
    deleted_profile.user.delete() 

post_delete.connect(delete_related_user, sender=Profile) 
+0

Danke für Ihre Antwort! Ich ging mit der Antwort von miki725, weil es ein wenig vollständiger und ein wenig kompakter war. Ich schätze deine Zeit sehr! – Nick

Verwandte Themen