В модели всё выглядит аккуратно: несколько
ForeignKey, on_delete=PROTECT и unique_together. Но внешний ключ связывает две таблицы, поэтому обеспечить такое ограничение сложнее, чем уникальность или проверку значения. Явное лучше неявного, а неявного поведения здесь хватает.Статья How to Get Foreign Keys Horribly Wrong разбирает, где появляются дублирующие индексы и как обнаружить блокирующую миграцию. Затем переходит к безопасному переносу внешнего ключа, обратимым операциям и конкурентному созданию индексов.
Перед следующим изменением схемы по ссылке стоит проверить ещё две вещи: когда нужен частичный индекс и в каком порядке выполнять миграционные операции.