Django ModelForm 复选框小部件

3 投票
3 回答
23599 浏览
提问于 2025-04-15 13:33

我现在遇到一个问题,可能是我忽略了一些很简单的东西。我在我的模型里有一个字段,应该允许用户通过复选框选择多个选项(在后台管理界面不一定要是复选框,只要在最终用户能看到的表单区域是复选框就可以)。目前我把这个字段设置成这样:

# Type of Media
MEDIA_CHOICES = (
    ('1', 'Magazine'),
    ('2', 'Radio Station'),
    ('3', 'Journal'),
    ('4', 'TV Station'),
    ('5', 'Newspaper'),
    ('6', 'Website'),
)
media_choice = models.CharField(max_length=25,
    choices=MEDIA_CHOICES)

不过我需要把它做成一个可以选择的复选框字段。当我创建一个ModelForm时,它默认想用下拉框。所以我自然就重写了这个字段,这样我得到了我想要的复选框。但是,当表单提交后,我在后台管理界面看时,似乎没有保存任何有用的信息。不过,数据库显示我确实选择了好几个选项,这算是个好兆头。但是,我该如何让这些选项在后台管理界面正确显示呢?

补充:顺便说一下,我很乐意接受文档链接作为答案,因为我感觉我可能只是忽略了一些显而易见的东西。

3 个回答

0

使用piquadrat的回答对我有效,但我需要添加一行代码来定义M2M(多对多)的查询集。可以查看这个链接

1

我刚开始研究用ModelForms来处理小部件的分配。在很多我看到的例子中,包括piquadrat的例子,表单的__init__方法被重写了。

我觉得这有点让人困惑,对我来说,直接重写想要的字段更自然:

class SomeModelForm(forms.ModelForm):
    some_field = forms.CharField(choices=MEDIA_CHOICES,
                                 widget=forms.CheckboxSelectMultiple)
    class Meta:
        model=SomeModel

注意:我使用的是Django 1.1。

16

在这种情况下,最简单的方法是把选项放到一个单独的模型里,然后使用多对多的关系。之后,你只需要把这个字段的模型表单的控件替换成 forms.CheckboxSelectMultiple,这样Django就会自动处理好一切。如果你坚持要用CharField,那你可能需要做一些像 这个代码片段 这样的事情。

@ 2. 评论:你是怎么替换控件的?这是我做的方式,效果很好:

class SomeModelForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(SomeModelForm, self).__init__(*args, **kwargs)
        self.fields['some_field'].widget = forms.CheckboxSelectMultiple()

撰写回答