Django:替换默认的ManyToMany窗体小部件

gue*_*tli 8 django drop-down-menu

我知道在django管理界面中替换ManyToMany Widget的人:

class SomeModelAdmin(admin.ModelAdmin):
    filter_horizontal = ('users',)
Run Code Online (Sandbox Code Playgroud)

但是如何在所有视图中替换默认小部件?

我想这可以在不改变我的代码或django中的一行的情况下实现.

如果我能在这个带有小部件的图片中使用作者部分(ManyToMany输入的两个框)这样的话会很棒:

在此输入图像描述

我可以使用ctrl+点击,但我的用户不能.他们想要一种更简单的方法

有没有办法在我的代码中没有很多更改的情况下替换所有选择多个小部件?

bri*_*pck 5

如果我不明白你的问题,请在评论中澄清。

Django表单小部件文档提供了几个预制小部件,您可以使用它们来指定表单中字段的呈现方式。

无需修改视图中的代码,我只需将widget关键字 arg 添加到适当的表单字段即可。

表单.py (v1)

class TestForm(forms.Form):
    CHOICES = (
    (1, "choice1"),
    (2, "choice2"),
    (3, "choice3"),
    )
    field = forms.ChoiceField(choices=CHOICES)
Run Code Online (Sandbox Code Playgroud)

这呈现为下拉菜单select

<select id="id_field" name="field">
  <option value="1">choice1</option>
  <option value="2">choice2</option>
  <option value="3">choice3</option>
</select>
Run Code Online (Sandbox Code Playgroud)

现在将widget关键字 arg 添加到我的字段中:

表单.py (v2)

field = forms.ChoiceField(choices=CHOICES, widget=forms.CheckboxSelectMultiple)
Run Code Online (Sandbox Code Playgroud)

这呈现为复选框列表:

<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>
Run Code Online (Sandbox Code Playgroud)

编辑

还可以添加 Django Admin 使用的小部件。看到Django 多选小部件了吗?有关此的更多信息。只需导入适当的小部件:

from django.contrib.admin.widgets import FilteredSelectMultiple
Run Code Online (Sandbox Code Playgroud)

并用它来代替。请注意,在这种特殊情况下,您还需要包含表单media以获得所需的效果。


ahm*_*med 5

您可以使用覆盖的基类 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
Run Code Online (Sandbox Code Playgroud)