我想像ManyToManyField
admin 一样在 admin 中显示 s filter_horizontal
,但是在用户输入过滤器字段时填充选项。有很多选项,一次加载它们需要很多时间。
我找到了django-ajax-filtered-fields但在我看来这有点过头了,因为它需要更改模型类,而我只想替换表单中的每个多选字段。
编写一个继承自的自定义小部件字段admin.widgets.FilteredSelectMultiple
似乎是正确的方法。所以我想推出我自己的小部件:
class MultiSelectWidget(FilteredSelectMultiple):
class Media:
# here should be some js to load options dynamically
js = (
"some_js_to_load_ajax_options.js",
)
def render_options(self, choices, selected_choices):
# this initializes the multiple select without any options
choices = [c for c in self.choices if str(c[0]) in selected_choices]
self.choices = choices
return super(MultiSelectWidget,
self).render_options([], selected_choices)
class MyAdminForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(MyAdminForm, self).__init__(*args, **kwargs)
self.fields['m2m_field'].widget = MultiSelectWidget('m2m_field', is_stacked=False)
class Meta:
model = MyModel
class MyAdmin(admin.ModelAdmin):
form = MyAdminForm
正确呈现。
但我不确定如何实现这个some_js_to_load_ajax_options.js
ajax 部分。我应该编写自己的 jQuery 片段还是修改SelectFilter2
附带的 jQuery 片段admin/media/js
?以前有人去过吗?
编辑:
虽然与问题的核心无关,因为我只想覆盖字段的小部件,较短的方法是使用formfield_overrides
:
class MultiSelectWidget(FilteredSelectMultiple):
# as above
class MyAdmin(admin.ModelAdmin):
formfield_overrides = {
models.ManyToManyField: {'widget': MultiSelectWidget},
}