Django-Autocomplete-Light: Взаимное исключение выделения нескольких полей
Я использую Django Autocomplete Light (DAL) с большим эффектом. Он прекрасно работает и работает уже много лет на одном из моих сайтов. Недавно я захотел улучшить небольшой аспект нашей реализации, а именно предотвратить множественный выбор одного и того же значения в группе виджетов DAL.
Конкретно мы построили динамическую Django форму, с помощью которой можно отправить список игроков. В таблице есть строка шаблона, и каждый раз, когда вы добавляете игрока, она копирует строку шаблона, корректирует id виджетов в копии по мере необходимости и вставляет ее в DOM (как новую строку).
Все это работает просто замечательно. Виджеты DAL отображаются в элементе select с именем и id в форме model-n-field
, которые обработчик POST прекрасно валидирует, и все хорошо.
Эти виджеты DAL выглядят в общем виде:
<select id="id_model-n-field" name="model-n-field" class="ModelChoiceField select2-hidden-accessible" data-autocomplete-light-language="en" data-autocomplete-light-url="/autocomplete/model/field" data-autocomplete-light-function="select2" data-select2-id="id_model-n-field" aria-hidden="true">
<option value="" selected="" data-select2-id="13">---------</option>
</select>
<span class="select2 select2-container select2-container--bootstrap select2-container--below select2-container--focus select2-container--open" dir="ltr" data-select2-id="12" style="width: 426.906px;">
<span class="selection">
<span class="select2-selection select2-selection--single ModelChoiceField" role="combobox" aria-haspopup="true" aria-expanded="true" tabindex="2" aria-disabled="false" aria-labelledby="select2-id_model-n-field-container" aria-owns="select2-id_model-n-field-results">
<span class="select2-selection__rendered" id="select2-id_model-n-field-container" role="textbox" aria-readonly="true">
<span class="select2-selection__placeholder">
</span>
</span>
<span class="select2-selection__arrow" role="presentation">
<b role="presentation"></b>
</span>
</span>
</span>
Мне еще предстоит выяснить, как, где и для чего обработчик клика для обратного вызова AJAX прикреплен к этому HTML, но я уверен, что он находится во внутренностях элемента Select2 и управляется различными атрибутами класса select2 (с некоторым onload запущенным JS, прикрепляющим обработчики событий к элементам определенных классов select2).
Я вижу в коде на стороне сервера, в обработчике AJAX, что приходит через запрос. В частности, модель и поле доступны через объект запроса в обработчике.
Теперь, поскольку это динамическая форма, с этим шаблоном, повторяющимся по запросу на стороне клиента, с именами и идентификаторами охватывающих select
элементов, получающих число n для отражения строки, на форме может быть несколько таких элементов.
Все это работает замечательно и работает уже много лет. Замечательная динамическая форма и механизм ввода формы.
Есть только одна маленькая идиосинкразия, которая также была в списке дел на протяжении многих лет, чтобы ее устранить, и на которую я обратил внимание сейчас. Можно выбрать одного и того же игрока в двух или более рядах, но не легальной подачей. В настоящее время это обнаруживается на стороне сервера и возвращается как ошибка валидации в Django.
Тогда передо мной стоит задача настроить виджет(ы) DAL так, чтобы обратный вызов AJAX (на data-autocomplete-light-url
) получал список выбранных значений во всех других виджетах DAL группы и мог отфильтровать их из возвращаемого списка.
Если этого не сделать, то можно найти способ подключиться к JS, обрабатывающему результаты, который (имея доступ к DOM) может удалить элементы, выбранные в других DAL-виджетах группы. Это, конечно, менее желательно, чем передача выбранных значений в AJAX URL (как GET параметры) по той простой причине, что DAL виджет запрашивает их по одной странице за раз, и фильтрация в идеале выполняется до пагинации, а не после (возможно, что существующий выбор более или менее уничтожит страницу, например, в последнем случае)
Мне интересно, существует ли парадигма, с помощью которой виджеты DAL могут быть настроены на отправку дополнительной информации вместе с AJAX запросом, в настраиваемой манере (информация предоставляется, скажем, функцией JS). В своих чтениях и блужданиях я пока не нашел такого варианта, но прежде чем я попытаюсь его разработать, я хотел бы воспользоваться коллективной мудростью сообщества.
Воображаемая парадигма:
- При создании виджета
autocomplete.ModelSelect2
в бэкенде на Python, называя JS функцию, которая будет вызываться для предоставления GET параметров AJAX запроса. - Написание функции в JS на стороне клиента, которая считывает все виджеты DAL в одной группе и возвращает GET-параметры, идентифицирующие выбранные элементы в других виджетах DAL.
Это кажется такой простой парадигмой, остается вопрос, реализована ли она или нет и доступна ли нам.