Я стремлюсь сделать «расширенный» фильтр_горизонтальный, один с большим количеством фильтров, но я не могу найти виджет для переопределения.
Я знаю, что он использует related_widget_wrapper.html, но если я хочу добавить к нему функциональные возможности, то какой виджет нужно переопределить.
На данный момент мое решение для резервного копирования состоит в том, чтобы создать полное решение javascript, добавив к нему выпадающий список при загрузке формы (созданный из javascript), и выполнить вызовы ajax для изменения фильтра ... но это кажется излишним.
Что я сделал до сих пор:
# Override filteredSelectMultiple, add javascript and add attributes on the tag to identify the element, and add parameter url that will contain the ajax call
class AjaxFilterHorizontalWidget(FilteredSelectMultiple):
def __init__(self, url, verbose_name = '', is_stacked=False, attrs=None, choices=()):
self.url = url
super().__init__(verbose_name, is_stacked, attrs, choices)
def get_context(self, name, value, attrs):
context = super().get_context(name, value, attrs)
context['widget']['attrs']['data-url'] = self.url
context['widget']['attrs']['data-ajax-select'] = '1'
return context
class Media:
js = ['admin/js/ajax_filter_horizontal.js']
Ajax_filter_horizontal.js
$(document).ready(function () {
$('select[data-ajax-select=1]').each(function (index, item) {
var currentRequest;
var url = $(item).data('url')
// var wrapper = $('#' + $(item).prop('id')).closest('.selector-available')
$(document).on('keyup', $('.selector-filter input'), function () {
if ($('.selector-filter input').val().length < 3) {
$(item).empty()
return
}
currentRequest = $.ajax({
url: url,
data: {q: $('.selector-filter input').val()},
beforeSend : function() {
if(currentRequest != null) {
currentRequest.abort();
}
},
success: function (data) {
$(item).empty()
let item_to = $('#' + $(item).prop('id').replace('_from', '_to'))
if (data.results.length > 500) {
$('#' + $(item).prop('id')).append('<option disabled value="" title="">Too many results, refine your search...</option>')
return
}
for (let instance of data.results) {
if ($('option[value='+instance.id+']', item_to).length == 0) {
$('#' + $(item).prop('id')).append('<option value="'+instance.id+'" title="'+instance.text+'">'+instance.text+'</option>')
}
}
SelectBox.init($(item).prop('id'))
}
})
});
});
});
Мне пришлось переопределить поле, просто чтобы удалить проверку (по какой-то причине проверка также выполняется для исходных значений, левая сторона filter_horizontal)
class AjaxMultipleChoiceField(MultipleChoiceField):
widget = AjaxFilterHorizontalWidget
def validate(self, value):
pass
"""Validate that the input is a list or tuple."""
# if self.required and not value:
# raise ValidationError(self.error_messages['required'], code='required')
Вот как я это называю:
self.fields['person'] = `AjaxMultipleChoiceField(widget=AjaxFilterHorizontalWidget(url= '/person-autocomplete-advanced/', verbose_name='People to invite'))`
Мне не удается найти, где предварительно заполнить значения в разделе "to", когда я редактирую существующее поле.