Я вижу два отдельных вопроса здесь:
Вы хотите наложить определенные ограничения на ваши данные.
Если ограничение нарушено, вы хотите отменить предыдущие операции. В частности, вы хотите отменить создание экземпляра Badge
, если какие-либо Restaurants
добавлены в тот же запрос, который нарушает ограничение.
Что касается 1, ваше ограничение является сложным, поскольку оно включает несколько таблиц. Это исключает ограничения базы данных (возможно, вы могли бы сделать это с помощью триггера) или простой проверки на уровне модели.
Ваш код выше, по-видимому, эффективен для предотвращения adds
, который нарушает ограничение. Обратите внимание, однако, что это ограничение также может быть нарушено, если идентификатор существующего Badge
изменяется. Предположительно, вы хотите предотвратить это? Если это так, вам нужно добавить аналогичную проверку в Badge
(например, в Badge.clean()
).
Что касается 2, если вы хотите, чтобы создание экземпляра Badge
было отменено при нарушении ограничения, необходимо убедиться, что операции заключены в транзакцию базы данных. Вы не рассказали нам о видах, где создавалась область этих объектов (пользовательские виды? Администратор Django?), Поэтому сложно дать конкретный совет. По сути, вы хотите иметь это:
with transaction.atomic():
badge_instance.save()
badge_instance.add(...)
Если вы это сделаете, исключение, выданное вашим сигналом M2M pre_add
, откатит транзакцию, и вы не получите остаток Badge
в вашей базе данных. Обратите внимание, что представления администратора по умолчанию выполняются в транзакции, поэтому это должно происходить, если вы используете администратора.
Другой подход заключается в проверке перед созданием объекта Badge
. См., Например, этот ответ об использовании ModelForm
проверки в администраторе Django.