Python 如何摆脱Django形式的RadioSelect产生的虚假选择

Python 如何摆脱Django形式的RadioSelect产生的虚假选择,python,django,django-forms,Python,Django,Django Forms,我正在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):

我正在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用户()也提出了同样的问题。我已经在那里尝试了公认的解决方案(如你所见),但那对我不起作用

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


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

即使没有blank=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)

设置
blank=False
(或删除它),并添加
default='Unspecified'
默认情况下
modelcoocefield使用的小部件在列表顶部将有一个空选项

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

自定义空标签:

field1 = forms.ModelChoiceField(queryset=..., empty_label="(Nothing)")
field2 = forms.ModelChoiceField(queryset=..., empty_label=None)
无空标签:

field1 = forms.ModelChoiceField(queryset=..., empty_label="(Nothing)")
field2 = forms.ModelChoiceField(queryset=..., empty_label=None)
Django=1.11

在Django 1.10之后,RadioSelect或其祖先中不再使用以下方法。这就是为什么upper小部件不会删除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)

尼基的回答似乎是正确的,但我想补充一点。如果我没有弄错的话,在下面的行中,choices=list(chain(self.choices,choices))chain需要额外的导入:从itertools导入chain如何在django 1.11中执行此操作即使在模型上
blank=False
时也会发生这种情况。