Я хочу отобразить ManyToManyField
s в админке так же, как filter_horizontal
, но заполняет опции, когда пользователь вводит в поле фильтра. Есть много вариантов, и загрузка их всех занимает много времени.
Я нашел django-ajax-Filter-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
, который идет с admin/media/js
? Кто-нибудь был там раньше?
редактировать:
Хотя это и не относится к сути вопроса, поскольку я хочу переопределить только виджет поля, более короткий путь заключается в использовании formfield_overrides
:
class MultiSelectWidget(FilteredSelectMultiple):
# as above
class MyAdmin(admin.ModelAdmin):
formfield_overrides = {
models.ManyToManyField: {'widget': MultiSelectWidget},
}