Django — удаление пользователей с помощью on_delete=models.КАСКАД вызывает проблемы с сигналами.post_delete

#python #django #django-models #django-signals

#python #django #django-модели #django-сигналы

Вопрос:

Мы используем Django 3.1 для наших веб-сайтов. У нас есть модель, User , которая связана с двумя SiteProfile моделями для двух веб-сайтов, а также связана с другими моделями, такими как Friend и UserEmailAddress . Все отношения связаны с on_delete=models.CASCADE . У нас также есть models.signals.post_delete сигналы для таких моделей, как Friend обновление количества друзей у пользователя, которое сохраняется в одной из SiteProfile моделей. Но проблема в том, что при удалении пользователя вызывается сигнал, а затем SiteProfile объект сохраняется, а затем я получаю исключение для django.db.utils.IntegrityError — нарушения внешних ключей. Раньше у нас была такая же проблема с UserEmailAddress моделью (адрес электронной почты пользователя), которую я исправил с помощью следующего кода:

 def delete(self, *args, **kwargs):
    if ((self.is_staff) or (self.is_superuser)):
        warnings.warn('Can’t delete staff user.')
        return False
    else:
        with transaction.atomic():
            for user_email_address in self.email_addresses.all():
                user_email_address.delete()
            return_value = super().delete(*args, **kwargs)
        return return_value
 

Но я хотел бы знать, есть ли лучший способ удалить пользователя со всеми связанными с ним объектами, которые есть on_delete=models.CASCADE , но без сохранения счетчиков в models.signals.post_delete базе данных? Могу ли я что-то проверить models.signals.post_delete , чтобы узнать, удаляется ли пользователь, а затем не сохранять счетчики? Поскольку я не хочу специально удалять какой-либо связанный объект в def delete методе — существует как минимум 5 таких моделей, не включая две SiteProfile модели.

Комментарии:

1. Зачем вообще сохранять количество друзей, которые есть у пользователя? Вы можете просто получить это, выполнив запрос, попробуйте заменить это поле свойством, которое выполняет запрос с использованием orm для получения значения, и теперь вам больше не нужен ваш сигнал!

2. Производительность @AbdulAzizBarkat. Для чтения поля из модели требуется примерно на 50% меньше времени, чем для запроса базы данных о количестве друзей, особенно для тысяч пользователей.