Как удалить все вложенные объекты, на которые есть ссылки на объект? - PullRequest
0 голосов
/ 24 октября 2018

У меня есть модель, которая установлена ​​как внешний ключ в нескольких моделях.Прямо сейчас, удаляя любой объект из модели, выдается ProtectedError, если на него ссылаются в любой из этих моделей.Я хочу позволить пользователю удалить объект со всеми защищенными объектами за одну операцию.

Я могу удалить первый слой защищенных объектов, просто вызвав

....    
except ProtectedError as e
    e.protected_objects.delete()
....

Но когда protected_objectsимеют свои собственные защищенные объекты, операция завершается неудачей и выбрасывает еще один второй слой ProtectedError.Чего я хочу добиться, так это удалить все защищенные объекты без разбора, в каком слое он существует.Я знаю, что это может быть опасной операцией для выполнения.Но могу ли я достичь этого без комплексного решения.Заранее спасибо.

Исходный код, где я пытаюсь выполнить операцию ajax:

try:
    obj_list = model.objects.filter(pk__in=pk_list)
    log_deletion(request, obj_list, message='Record Deleted')
    obj_list.delete()
    return JsonResponse({'success': True, 'status_message': '{0} record(s) has been deleted successfully.'.format(len(pk_list))})
except ProtectedError as e:
    e.protected_objects.delete()
    return JsonResponse({'success': False, 'status_message': 'This operation cannot be executed. One or more objects are in use.'})

Ответы [ 2 ]

0 голосов
/ 24 октября 2018

Возможно, вы не захотите использовать on_delete=models.PROTECT в определении внешних ключей.Рассматривали ли вы при удалении вместо CASCADE?Если вы используете каскад, вам не нужно сначала перебирать зависимости, чтобы удалить их.

Вместо:

class OtherModel(models.Model):
    link = models.ForeignKey("Link", on_delete=models.PROTECT)

Вы можете определить модель следующим образом:

class OtherModel(models.Model):
    link = models.ForeignKey("Link", on_delete=models.CASCADE)

При удалении моделей от администратора, которые используют CASCADE, будет отображаться промежуточная страница со списком всех зависимых объектов, которые также будут удалены.

0 голосов
/ 24 октября 2018

В общем, вы можете использовать цикл:

...
except ProtectedError as e:
    obj = e.protected_objects
    while True:
        try:
            obj.delete()
        except ProtectedError as e:
            obj = e.protected_objects
        else:
            break
...

Чтобы записать, в каком слое происходят ошибки, вы можете добавить счетчик:

from itertools import count

obj_list = model.objects.filter(pk__in=pk_list)
for layer in count():
    try:
        log_deletion(request, obj_list, message='Record Deleted in layer {}'.format(layer))
        obj_list.delete()
    except ProtectedError as e:
        obj_list = e.protected_objects
    else:
        if layer == 0:
            return JsonResponse({'success': True, 'status_message': '{0} record(s) has been deleted successfully.'.format(len(pk_list))})
        else:
            return JsonResponse({'success': False, 'status_message': 'This operation cannot be executed. One or more objects are in use.'})
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...