IntegrityError: нарушение внешнего ключа при удалении - PullRequest
5 голосов
/ 30 марта 2010

У меня есть модель заказа и отгрузки. Отгрузка имеет внешний ключ для заказа.

class Order(...):
   ...

class Shipment()
   order = m.ForeignKey('Order')
   ...

Теперь в одном из моих представлений я хочу удалить объект заказа вместе со всеми связанными объектами. Поэтому я вызываю order.delete ().

У меня Django 1.0.4, PostgreSQL 8.4, и я использую промежуточное ПО транзакций, поэтому весь запрос заключен в одну транзакцию.

Проблема в том, что после order.delete () я получаю:

...
File "/usr/local/lib/python2.6/dist-packages/django/db/backends/__init__.py", line 28, in _commit
return self.connection.commit()

IntegrityError: update or delete on table "main_order" violates 
foreign key constraint "main_shipment_order_id_fkey" on table "main_shipment"
DETAIL:  Key (id)=(45) is still referenced from table "main_shipment".

Я проверял в connection.queries, что правильные запросы выполняются в правильном порядке. Первая партия удаляется, после чего django выполняет удаление в строке заказа:

{'time': '0.000', 'sql': 'DELETE FROM "main_shipment" WHERE "id" IN (17)'},
{'time': '0.000', 'sql': 'DELETE FROM "main_order" WHERE "id" IN (45)'}

Внешний ключ имеет значение ON DELETE NO ACTION (по умолчанию) и изначально откладывается. Я не знаю, почему я получаю нарушение ограничения внешнего ключа.

Я также попытался зарегистрировать сигнал pre_delete и вручную удалить объекты отгрузки, прежде чем вызывается удаление по заказу, но это привело к той же ошибке.

Я могу изменить поведение ON DELETE для этого ключа в Postgres, но это был бы просто взлом, интересно, если у кого-то есть лучшее представление о том, что здесь происходит.

Есть также небольшая деталь, моя модель Order наследуется от модели Cart, так что на самом деле в ней нет поля id, но cart_ptr_id, и после выполнения DELETE для ордера в корзине также есть DELETE, но это кажется не связанным? к проблеме с доставкой -> заказ, поэтому я упростил ее в примере.

1 Ответ

4 голосов
/ 30 марта 2010

ДЕТАЛИ: Ключ (id) = (45) по-прежнему ссылка из таблицы "main_shipment".

По-прежнему существует запись, ссылающаяся на идентификатор 45. Ранее вы удалили запись 17 в main_shipment, но могут быть и другие. Вы должны удалить все записи в main_shipment со ссылкой на id 45 в main_order. Если нет, база данных защищает вас от нанесения вреда вашим данным.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...