ManyToManyField
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
、付属の変更を行う必要がありadmin/media/js
ますか? 誰か前に行ったことある?
編集:
質問の核心とは関係ありませんが、フィールドのウィジェットのみをオーバーライドしたいので、より短い方法は次を使用することformfield_overrides
です:
class MultiSelectWidget(FilteredSelectMultiple):
# as above
class MyAdmin(admin.ModelAdmin):
formfield_overrides = {
models.ManyToManyField: {'widget': MultiSelectWidget},
}