Django IntegrityError: Как обработать ForeignKeyViolation в представлении с удалением?
Я столкнулся с проблемой при попытке удаления записей в Django. У меня есть функция удаления для компаний, но иногда я сталкиваюсь с IntegrityError, если у компании есть связанные записи в другой таблице. Я пробовал обрабатывать IntegrityError, но это не помогает - ошибка возникает после блока try-except и приводит к ошибке 500. Вот мой код:
@login_required(login_url=reverse_lazy('autintification'))
def delete_cp_company(request):
db_name = LOCAL_DB if DEBUG else request.get_host().split(".")[0]
cp_company_ids = json.loads(request.POST.get('cp_company_ids'))
no_del = []
for ids in cp_company_ids:
company = CP_company_for_pattern.objects.using(db_name).get(id=ids)
print('id', ids)
try:
company.delete()
except:
no_del.append({
'id': company.id,
'name': company.com_name,
})
return JsonResponse(data={'no_delete': no_del})
Вот JavaScript, который отправляет запрос на удаление:
function delete_cp_company() {
let check_box = $('.cp_company_list_block .check_for_choose_item');
let ids_to_delete = [];
for (let i = 0; i < check_box.length; i++) {
if (check_box[i].checked) {
let deleted_tr = $(check_box[i]).closest('tr');
let deleted_tr_id = deleted_tr.data("id");
ids_to_delete.push(deleted_tr_id);
}
}
$.ajax({
url: "/delete_cp_company",
method: "POST",
data: {
cp_company_ids: JSON.stringify(ids_to_delete),
csrfmiddlewaretoken: $('input[name=csrfmiddlewaretoken]').val(),
},
enctype: "multipart/form-data",
dataType: 'json',
success: function (data) {
processCompanyDelete(ids_to_delete, data.no_delete)
},
error: function (xhr, status, error) {
console.error('AJAX Error: ' + status + ' - ' + error);
},
});
}
Я пробовал обрабатывать IntegrityError в блоке try-except, но ошибка по-прежнему вызывает ответ 500. Я также пробовал добавить более специфическую обработку ошибок и использовать транзакции Django, но, похоже, ничего не помогает. Основная проблема заключается в том, что исключение возникает после блока try-except, когда Django пытается зафиксировать транзакцию.
Вот ошибка, которую я получаю:
id 11
id 4
Internal Server Error: /delete_cp_company
Traceback (most recent call last):
File "/path/to/django/db/backends/base/base.py", line 253, in _commit
return self.connection.commit()
psycopg2.errors.ForeignKeyViolation: update or delete on table "CRM_App_cp_company_for_pattern" violates foreign key constraint "CRM_App_contract_tab_our_company_id_370011ff_fk_CRM_App_c" on table "CRM_App_contract_table"
DETAIL: Key (id)=(4) is still referenced from table "CRM_App_contract_table".
The above exception was the direct cause of the following exception:
File "/path/to/django/db/utils.py", line 90, in __exit__
raise dj_exc_value.with_traceback(traceback) from exc_value
File "/path/to/django/db/backends/base/base.py", line 253, in _commit
return self.connection.commit()
django.db.utils.IntegrityError: update or delete on table "CRM_App_cp_company_for_pattern" violates foreign key constraint "CRM_App_contract_tab_our_company_id_370011ff_fk_CRM_App_c" on table "CRM_App_contract_table"
DETAIL: Key (id)=(4) is still referenced from table "CRM_App_contract_table".
HTTP POST /delete_cp_company 500 [0.11, 127.0.0.1:58081]
Как правильно обработать эту ошибку, чтобы она не вызывала ошибку 500?
Ошибка говорит, что существует объект с внешним ключом к этой компании, и если вы удалите компанию, то этот внешний ключ будет равен null, что недопустимо.
Скорее всего, в вашем models.py у вас есть внешний ключ с null=False
и on_delete=models.DO_NOTHING
.
class CRM_App_contract_table(models.Model):
company = models.ForeignKey(Company, on_delete=models.DO_NOTHING)
Так что вам нужно либо изменить это на null=True
, либо на models.CASCADE