【问题标题】:How to get rid of the bogus choice generated by RadioSelect of Django Form如何摆脱 Django Form 的 RadioSelect 生成的虚假选择
【发布时间】:2011-08-15 00:09:57
【问题描述】:

我在 Django 1.3 上使用 ModelForm。

models.py:

class UserProfile(models.Model):
...
gender = models.CharField(max_length=1, blank=True, choices=(('M', 'Male'), ('F', 'Female'), ('Unspecified', '')), default='M')
...

forms.py:

class UserProfileForm(ModelForm):
    class Meta:
        model = UserProfile
        fields = ('gender')
        widgets = {
            'gender': forms.RadioSelect(),
        }

当这个小部件被渲染成 HTML 时,我得到了

<ul> 
<li><label for="id_gender_0"><input type="radio" id="id_gender_0" value="" name="gender" />---------</label></li> 
<li><label for="id_gender_1"><input checked="checked" type="radio" id="id_gender_1" value="M" name="gender" /> Male</label></li> 
<li><label for="id_gender_2"><input type="radio" id="id_gender_2" value="F" name="gender" />Female</label></li> 
<li><label for="id_gender_3"><input type="radio" id="id_gender_3" value="" name="gender" /> Unspecified</label></li> 
</ul> 

问题: 我怎样才能摆脱虚假的选择“--------”?

几个月前另一个 stackoverflow 用户 (Here) 提出了同样的问题。我已经尝试了那里接受的解决方案(如您所见),但这对我不起作用。

【问题讨论】:

    标签: python django django-forms


    【解决方案1】:

    即使没有空白=True,它也会显示额外的输入。我创建了一个新的小部件:

    from itertools import chain
    from django.forms import RadioSelect
    from django.utils.encoding import force_unicode
    
    class RadioSelectNotNull(RadioSelect):
        def get_renderer(self, name, value, attrs=None, choices=()):
            """Returns an instance of the renderer."""
            if value is None: value = ''
            str_value = force_unicode(value) # Normalize to string.
            final_attrs = self.build_attrs(attrs)
            choices = list(chain(self.choices, choices))
            if choices[0][0] == '':
                choices.pop(0)
            return self.renderer(name, str_value, final_attrs, choices)
    

    【讨论】:

    • NickJ 的回答似乎是正确的,但我想补充一件事。如果我没记错的话,在下面这行中,choices = list(chain(self.choices,choices)) chain 需要额外的导入: from itertools import chain
    • 如何在 django 1.11 中实现
    【解决方案2】:

    设置blank=False(或直接删除)并添加default='Unspecified'

    【讨论】:

      【解决方案3】:

      您可以在设置小部件时设置选项。它显示 ---- 因为在您的模型中您有空白 = True。

      只需使用小部件的选项 arg 并将其设置为您在模型中设置的选项。

      【讨论】:

      • 即使blank=False 出现在我身上也会发生这种情况。
      【解决方案4】:

      默认情况下,ModelChoiceField 使用的小部件将在列表顶部有一个空选项。

      您可以使用 empty_label 属性更改此标签的文本(默认为“------”),或者您可以通过将 empty_label 设置为 None 来完全禁用空标签:

      自定义空标签:

      field1 = forms.ModelChoiceField(queryset=..., empty_label="(Nothing)")
      

      没有空标签:

      field2 = forms.ModelChoiceField(queryset=..., empty_label=None)
      

      【讨论】:

        【解决方案5】:

        Django

        RadioSelectNotNull 小部件

        from itertools import chain
        from django.forms import RadioSelect
        from django.utils.encoding import force_unicode
        
        class RadioSelectNotNull(RadioSelect):
        """
        A widget which removes the default '-----' option from RadioSelect
        """
            def get_renderer(self, name, value, attrs=None, choices=()):
                """Returns an instance of the renderer."""
                if value is None: value = ''
                str_value = force_unicode(value) # Normalize to string.
                final_attrs = self.build_attrs(attrs)
                choices = list(chain(self.choices, choices))
                if choices[0][0] == '':
                    choices.pop(0)
                return self.renderer(name, str_value, final_attrs, choices)
        

        Django >= 1.11

        在 Django 1.10 之后,RadioSelect 或其祖先中不再有以下方法。这就是为什么上部小部件不会删除 RadioSelect 生成的虚假选择的原因。

        def get_renderer(self, name, value, attrs=None, choices=()):
        

        因此,要删除 RadioSelect 生成的虚假选择,请使用以下小部件。我已经对此进行了测试,直到 Django 2.0

        from django.forms import RadioSelect
        class RadioSelectNotNull(RadioSelect):
            """
            A widget which removes the default '-----' option from RadioSelect
            """
            def optgroups(self, name, value, attrs=None):
                """Return a list of optgroups for this widget."""
                if self.choices[0][0] == '':
                    self.choices.pop(0)
                return super(RadioSelectNotNull, self).optgroups(name, value, attrs)
        

        【讨论】:

          猜你喜欢
          • 2011-03-02
          • 1970-01-01
          • 2013-12-24
          • 1970-01-01
          • 1970-01-01
          • 2020-06-17
          • 2012-01-03
          • 2019-05-03
          • 1970-01-01
          相关资源
          最近更新 更多