Как избавиться от фиктивного выбора, созданного RadioSelect of Django Form

Я использую ModelForm для Django 1.3.

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 месяцев назад (Здесь). Я попробовал принятое решение там (как вы можете видеть), но это не сработало для меня.

Ответ 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)

Ответ 2

Установите blank=False (или просто удалите его), а также добавьте default='Unspecified'

Ответ 3

Вы можете установить параметры при настройке виджета. Он показывает ----, потому что в вашей модели у вас пусто = True.

Просто используйте аргументы arg виджета и установите его в соответствии с параметрами, заданными в вашей модели.

Ответ 4

По умолчанию виджет, используемый ModelChoiceField, будет иметь пустой выбор в верхней части списка.

Вы можете изменить текст этого ярлыка (который по умолчанию - "---------" ) с атрибутом empty_label, или вы можете полностью отключить пустую метку, установив для параметра empty_label значение None:

Пользовательская пустая метка:

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

Нет пустой метки:

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

Ответ 5

Django & lt; = 1,10

Виджет 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)

Джанго> = 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)