Джанго: замена виджета ManyToMany форм
Я знаю, кто должен заменить виджет ManyToMany в интерфейсе администратора django:
class SomeModelAdmin(admin.ModelAdmin):
filter_horizontal = ('users',)
но как заменить виджет по умолчанию во всех ракурсах?
Я думаю, это может быть реализовано без изменения одной строки в моем коде или в django.
было бы здорово, если бы я мог что-то вроде авторской части (две коробки для ввода ManyToMany) на этой картинке с виджетом:
Я могу использовать ctrl + нажмите, но мои пользователи не могут. Они хотят более легкого пути.
есть ли способ заменить все виджеты select-multiple без многих изменений в моем коде?
3 ответов
если я не понимаю ваш вопрос, пожалуйста, уточните в комментариях.
на Django Форма Виджеты Документация предлагает несколько готовых виджетов, которые можно использовать, чтобы указать, как отображается поле в форме.
без изменения кода в моих представлениях я могу просто добавить widget
ключевое слово arg в соответствующие поля формы.
forms.py (v1)
class TestForm(forms.Form):
CHOICES = (
(1, "choice1"),
(2, "choice2"),
(3, "choice3"),
)
field = forms.ChoiceField(choices=CHOICES)
это отображается как выпадающее меню select
:
<select id="id_field" name="field">
<option value="1">choice1</option>
<option value="2">choice2</option>
<option value="3">choice3</option>
</select>
Теперь добавляем widget
ключевое слово arg для моего поля:
forms.py (v2)
field = forms.ChoiceField(choices=CHOICES, widget=forms.CheckboxSelectMultiple)
это отображается как список флажков:
<ul id="id_field">
<li>
<label for="id_field_0"><input id="id_field_0" name="field" type="checkbox" value="1" /> choice1</label>
</li>
<li>
<label for="id_field_1"><input id="id_field_1" name="field" type="checkbox" value="2" /> choice2</label>
</li>
<li>
<label for="id_field_2"><input id="id_field_2" name="field" type="checkbox" value="3" /> choice3</label>
</li>
</ul>
редактировать
также можно добавить виджеты, которые используются администратором Django. См.Django multi-выберите виджет? для получения дополнительной информации об этом. Просто импортируйте соответствующий виджет:
from django.contrib.admin.widgets import FilteredSelectMultiple
и использовать это вместо этого. Обратите внимание, что в этом в частном случае вам также нужно будет включить форму media
чтобы получить желаемый эффект.
вы можете использовать базовый класс, который ovride formfield_for_manytomany
from django.contrib.admin import widgets
class ManyToManyAdmin(admin.ModelAdmin):
def formfield_for_manytomany(self, db_field, request=None, **kwargs):
kwargs['widget']= widgets.FilteredSelectMultiple(
db_field.verbose_name,
db_field.name in self.filter_vertical
)
return super(admin.ModelAdmin, self).formfield_for_manytomany(
db_field, request=request, **kwargs)
class SomeModelAdmin(ManyToManyAdmin):
pass
вам нужно заменить виджеты по умолчанию в формах django.
это работает для меня:
from django import forms
from django.contrib.admin.widgets import FilteredSelectMultiple
# replace MultipleChoise in Forms
forms.MultipleChoiceField.widget = FilteredSelectMultiple("verbose name", is_stacked=False)
# replace MultipleChoise in ModelForms
forms.ModelMultipleChoiceField.widget = FilteredSelectMultiple("verbose name", is_stacked=False)
- добавить код выше в файл
forms_setup.py
в вашем основном проекте -
затем в
settings.py
импорт файлаforms_setup.py
:from .forms_setup import *