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

Вернуться на верх