Django - 将formset中的BooleanField显示为一组单选按钮

时间:2012-03-18 14:54:22

标签: django django-models django-widget django-forms

我有以下型号:

class Profile(models.Model):
    verified = models.BooleanField(default=False)

    def primary_phone(self):
        return self.phone_set.get(primary=True)

class Phone(models.Model):
    profile = models.ForeignKey(Profile)
    type = models.CharField(choices=PHONE_TYPES, max_length=16)
    number = models.CharField(max_length=32)
    primary = models.BooleanField(default=False)

    def save(self, force_insert=False, force_update=False, using=None):
        if self.primary:
            # clear the primary attribute of other phones of the related profile
            self.profile.phone_set.update(primary=False)
        self.save(force_insert, force_update, using)

我在ModelForm中使用Phone作为formset。我要做的是在Phone.primary的每个实例旁边显示Phone作为单选按钮。如果我将primary设为RadioSelect小部件:

class PhoneForm(ModelForm):
    primary = forms.BooleanField(widget=forms.RadioSelect( choices=((0, 'False'), (1, 'True')) ))

    class Meta:
        from accounts.models import Phone
        model = Phone
        fields = ('primary', 'type', 'number', )

它会显示两个单选按钮,它们将在每个实例旁边分组。相反,我正在寻找一种方法,在每个实例旁边只显示一个单选按钮(应为该实例设置primary=True),并将所有单选按钮组合在一起,这样只有其中一个可以被选中。

我也在寻找一种干净的方式来做这件事,我可以手动完成上述大部分操作 - 在我的脑海中 - 但我很想知道是否有更好的方法来实现它,django风格方式。

有人有个主意吗?

1 个答案:

答案 0 :(得分:3)

好的,你在这里遇到两个困境。首先,您需要通过为其提供相同的HTML名称属性来对来自不同表单集的所有无线电选择进行分组。我使用下面的 add_prefix 覆盖来做到这一点。

然后你必须确保你的帖子数据中的'主要'字段返回一些有意义的东西,你可以从中确定选择了哪个电话(在POST数据中应该只有一个'name'值b / c你可以只从组内选择一个单选按钮)。通过分配正确的前缀值(这需要在 _ init _ 下完成,以便您可以访问自我实例),您将能够关联“主要”使用其余表单数据的值(通过自定义保存方法)。

我测试了一个带有以下内容的formset,它吐出了正确的html。所以试一试:

class PhoneForm(ModelForm):
    def __init__ (self, *args, **kwargs)
        super(PerstransForm, self).__init__(*args, **kwargs)
        self.fields['primary'] = forms.BooleanField( widget = forms.RadioSelect(choices=((self.prefix, 'This is my Primary Phone'),))

    #enter your fields except primary as you had before.
    def add_prefix(self, field):
        if field == 'primary': return field
        else: return self.prefix and ('%s-%s' % (self.prefix, field)) or field