2012-10-05 18 views
28

tengo el siguiente modelo:OneToOneField y eliminación de

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) 

Cuando se utiliza la administración de Django para eliminar el usuario, el perfil se elimina, así, que es lo que quiero. Sin embargo, cuando se utiliza la administración de Django para eliminar el perfil, el usuario hace no se eliminan, que es no lo que yo quiero. ¿Cómo puedo hacerlo para que eliminar el perfil también elimine al usuario?

Respuesta

41

Desde Profile enlaces a User, que es el modelo depende de la relación. Por lo tanto, cuando elimina un usuario, elimina todos los modelos dependientes. Sin embargo, cuando elimina un perfil, ya que User no depende del perfil, no se elimina.

Desafortunadamente, según on_delete Django docs, no hay regla on_delete que elimine las relaciones principales. Con el fin de hacer eso, puede sobrescribir la Profile 's delete método:

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

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

Entonces cuando se hace:

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

también puede eliminar el usuario del perfil. Sin embargo el método delete no se llamará cuando se elimina perfiles utilizando QuerySets (que es lo que se llama en Django Admin) desde entonces Django usa SQL DELETE para eliminar los objetos a granel:

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

En ese caso, según lo recomendado por Django docs, tendrá que usar la señal post_delete (docs).

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

¡Muchas gracias! Todavía soy nuevo en Django, por lo que en caso de cualquier otro noobs Django encuentran esto, he tenido que añadir un dispatch_uid al decorador @receiver con el fin de que funcione. ¡Pero después de eso, funcionó de maravilla! – Nick

7

uso de una señal en el método de eliminación del Profile 's ir y eliminar la relacionada con el usuario:

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

¡Gracias por su respuesta! Terminé yendo con la respuesta de miki725 porque era un poco más completa y un poco más compacta. ¡Realmente aprecio tu tiempo, sin embargo! – Nick

Cuestiones relacionadas