Джанго: замена виджета ManyToMany форм

Я знаю, кто должен заменить виджет ManyToMany в интерфейсе администратора django:

class SomeModelAdmin(admin.ModelAdmin):
    filter_horizontal = ('users',)

но как заменить виджет по умолчанию во всех ракурсах?

Я думаю, это может быть реализовано без изменения одной строки в моем коде или в django.

было бы здорово, если бы я мог что-то вроде авторской части (две коробки для ввода ManyToMany) на этой картинке с виджетом:

enter image description here

Я могу использовать 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)
  1. добавить код выше в файл forms_setup.py в вашем основном проекте
  2. затем в settings.py импорт файла forms_setup.py:

    from .forms_setup import *