【问题标题】:Django BooleanField as radio buttons?Django BooleanField 作为单选按钮?
【发布时间】:2010-10-25 16:14:51
【问题描述】:

在 Django 1.0.2 中是否有一个小部件可以将 models.BooleanField 呈现为两个单选按钮而不是一个复选框?

【问题讨论】:

    标签: django django-models django-forms


    【解决方案1】:

    Django 1.2 为模型表单添加了“widgets”元选项:

    在您的 models.py 中,为您的布尔字段指定“选择”:

    BOOL_CHOICES = ((True, 'Yes'), (False, 'No'))
    
    class MyModel(models.Model):
        yes_or_no = models.BooleanField(choices=BOOL_CHOICES)
    

    然后,在您的 forms.py 中,为该字段指定 RadioSelect 小部件:

    class MyModelForm(forms.ModelForm):
        class Meta:
            model = MyModel
            widgets = {
                'yes_or_no': forms.RadioSelect
            }
    

    我已经使用 SQLite 数据库对此进行了测试,该数据库还将布尔值存储为 1/0 值,并且在没有自定义强制函数的情况下似乎可以正常工作。

    【讨论】:

    • 迄今为止最干净和最“Django”的解决方案。谢谢!
    • 这很棒。我会稍微修改一下,通过使用from django.utils.translation import ugettext_lazy as _ 并将BOOL_CHOICES 更新为:BOOL_CHOICES = ((True, _('Yes')), (False, _('No'))) 来允许本地化版本的“是”和“否”
    • 我认为用于本地化的额外代码会分散注意力。给读者的练习;)
    • 在表单中定义选项更简单:stackoverflow.com/a/8833454
    【解决方案2】:

    您可以通过覆盖 ModelForm 中的字段定义来做到这一点:

    class MyModelForm(forms.ModelForm):
        boolfield = forms.TypedChoiceField(
                       coerce=lambda x: x == 'True',
                       choices=((False, 'False'), (True, 'True')),
                       widget=forms.RadioSelect
                    )
    
        class Meta:
             model = MyModel
    

    【讨论】:

    • 不幸的是这不起作用,因为 coerce=bool 被传递一个字符串值,而不是布尔值和 bool("False") => True。所以我不得不编写一个自定义强制函数来获取字符串值并转换为布尔值,然后它就起作用了。谢谢指点。
    • 真的应该更新,因为正如@dar 所指出的,这实际上不会工作,因为bool('False') => True
    • 不应该选择(('False', False), ('True', True))吗?换句话说,他们不应该反过来吗?
    • 刚刚遇到这个,并想注意这个答案的更新。每this ticket:TypedChoiceField(coerce=lambda x: x =='True', choices=((False, 'No'), (True, 'Yes')), widget=forms.RadioSelect)
    • 这种方式字段在form.changed_data中显示不正确,因为在比较表单输入值和初始值时使用了强制。将 bool True 传递给强制会导致 False,而传递给强制的表单结果中的“True”会导致 True,因此被称为 changed_data。我用以下强制解决了它: coerce=lambda x: ((x != 'False' and x is not False) or False)
    【解决方案3】:

    稍微修改 Daniel Roseman 的答案,您可以通过使用 ints 来简洁地解决 bool("False") = True 问题:

    class MyModelForm(forms.ModelForm):
        boolfield = forms.TypedChoiceField(coerce=lambda x: bool(int(x)),
                       choices=((0, 'False'), (1, 'True')),
                       widget=forms.RadioSelect
                    )
    
    class Meta:
         model = MyModel
    

    【讨论】:

    • 这不适用于我的编辑表单。该字段的当前值不会从模型中拉出。我改用了 eternicode 的答案。
    【解决方案4】:

    这是我能找到的最简单的方法(我使用的是 Django 1.5):

    class MyModelForm(forms.ModelForm):
        yes_no = forms.BooleanField(widget=RadioSelect(choices=[(True, 'Yes'), 
                                                                (False, 'No')]))
    

    【讨论】:

    • 这应该是正确的答案。
    • 验证此解决方案是否有效,但请参阅note in the docs。您需要在字段上设置 required=False。
    【解决方案5】:

    在 Django 1.6 中,以下内容对我有用:

    class EmailSettingsForm(ModelForm):
    
        class Meta:
            model = EmailSetting
            fields = ['setting']
            widgets = {'setting': RadioSelect(choices=[
                (True, 'Keep updated with emails.'),
                (False, 'No, don\'t email me.')             
            ])}
    

    【讨论】:

      【解决方案6】:

      与@eternicode 的回答相同,但不修改模型:

      class MyModelForm(forms.ModelForm):
          yes_no = forms.RadioSelect(choices=[(True, 'Yes'), (False, 'No')])
      
          class Meta:
              model = MyModel
              widgets = {'boolfield': yes_no}
      

      我认为这只适用于 Django 1.2+

      【讨论】:

      • boolfield 指的是什么?
      • @DataGreed 将其替换为您的字段名称。
      【解决方案7】:

      这是一个使用 lambda 的快速而肮脏的强制函数,它解决了 "False" -> True 问题:

      ...
      boolfield = forms.TypedChoiceField(coerce=lambda x: x and (x.lower() != 'false'),
      ...
      

      【讨论】:

        【解决方案8】:

        由于@Daniel Roseman 的答案存在问题,bool('False') --> 是的,所以现在我在这里将两个答案合并为一个解决方案。

        def boolean_coerce(value):
            # value is received as a unicode string
           if str(value).lower() in ( '1', 'true' ):
               return True
           elif str(value).lower() in ( '0', 'false' ):
               return False
           return None
        
        class MyModelForm(forms.ModelForm):
        boolfield = forms.TypedChoiceField(coerce= boolean_coerce,
                       choices=((False, 'False'), (True, 'True')),
                       widget=forms.RadioSelect
                    )
        
        class Meta:
             model = MyModel
        

        现在这将起作用:)

        【讨论】:

          【解决方案9】:

          还要记住 MySQL 使用 tinyint 作为布尔值,所以 True/False 实际上是 1/0。我使用了这个强制函数:

          def boolean_coerce(value):
              # value is received as a unicode string
              if str(value).lower() in ( '1', 'true' ):
                  return True
              elif str(value).lower() in ( '0', 'false' ):
                  return False
              return None
          

          【讨论】:

            【解决方案10】:

            另一种解决方案:

            from django import forms
            from django.utils.translation import ugettext_lazy as _
            
            def RadioBoolean(*args, **kwargs):
                kwargs.update({
                    'widget': forms.RadioSelect,
                    'choices': [
                        ('1', _('yes')),
                        ('0', _('no')),
                    ],
                    'coerce': lambda x: bool(int(x)) if x.isdigit() else False,
                })
                return forms.TypedChoiceField(*args, **kwargs)
            

            【讨论】:

              【解决方案11】:

              django 3.0 版更新:

              BOOLEAN_CHOICES = (('1', 'True label'), ('0', 'False label'))
                # Filtering fields
                  True_or_false_question = forms.ChoiceField(
                      label="Some Label3",
                # uses items in BOOLEAN_CHOICES
                      choices = BOOLEAN_CHOICES,
                      widget = forms.RadioSelect
                  )
              

              它给出了一个要点按钮列表,我不知道如何让它不这样做

              【讨论】:

              猜你喜欢
              相关资源
              最近更新 更多
              热门标签