Подтвердить что ты не робот

OneToOneField и удаление

У меня есть следующая модель:

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)

При использовании администратора Django для удаления пользователя профиль также удаляется, и это то, что я хочу. Однако при использовании администратора Django для удаления профиля пользователь не удаляется, а это не то, что я хочу. Как я могу сделать это так, чтобы удаление профиля также удаляло пользователя?

4b9b3361

Ответ 1

Так как Profile ссылки на User, это зависимая модель в отношении. Поэтому, когда вы удаляете пользователя, он удаляет все зависимые модели. Однако при удалении профиля, поскольку User не зависит от профиля, он не удаляется.

К сожалению, согласно on_delete Django docs, не существует правила on_delete, которое удаляет родительские отношения. Для этого вы можете перезаписать метод Profile delete:

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

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

Тогда при выполнении:

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

также удалит пользователя профиля. Однако метод delete не будет вызываться при удалении профилей с использованием запросов (это то, что вызывается в Django Admin), с тех пор Django использует SQL DELETE для удаления объектов в массе:

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

В этом случае, как рекомендовано Django docs, вам нужно будет использовать сигнал 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()

Ответ 2

Использовать сигнал в методе удаления Profile для перехода и удаления связанного пользователя:

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)