【发布时间】:2019-08-15 03:23:16
【问题描述】:
我的目标是制作一个“高级”filter_horizontal,一个具有更多过滤器的过滤器,但我似乎无法找到要覆盖的小部件。 我知道它使用了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”部分中预填充值的位置。
【问题讨论】:
标签: django django-admin django-admin-filters