[Django]-Empty Label ChoiceField Django

25๐Ÿ‘

โœ…

Hereโ€™s the solution that I used:

from myapp.models import COLORS

COLORS_EMPTY = [('','---------')] + COLORS

class ColorBrowseForm(forms.Form):
    color = forms.ChoiceField(choices=COLORS_EMPTY, required=False, widget=forms.Select(attrs={'onchange': 'this.form.submit();'}))
๐Ÿ‘คNick B

67๐Ÿ‘

See the Django 1.11 documentation on ChoiceField. The โ€™empty valueโ€™ for the ChoiceField is defined as the empty string '', so your list of tuples should contain a key of '' mapped to whatever value you want to show for the empty value.

### forms.py
from django.forms import Form, ChoiceField

CHOICE_LIST = [
    ('', '----'), # replace the value '----' with whatever you want, it won't matter
    (1, 'Rock'),
    (2, 'Hard Place')
]

class SomeForm (Form):

    some_choice = ChoiceField(choices=CHOICE_LIST, required=False)

Note, you can avoid a form error if you want the form field to be optional by using required=False

Also, if you already have a CHOICE_LIST without an empty value, you can insert one so it shows up first in the form drop-down menu:

CHOICE_LIST.insert(0, ('', '----'))
๐Ÿ‘คFiver

8๐Ÿ‘

You can try this (assuming your choices are tuples):

blank_choice = (('', '---------'),)
...
color = forms.ChoiceField(choices=blank_choice + COLORS)
year = forms.ChoiceField(choices=blank_choice + YEAR_CHOICES)

Also, I canโ€™t tell from your code whether this is a form or a ModelForm, but it itโ€™s the latter, no need to redefine the form field here (you can include the choices=COLORS and choices=YEAR_CHOICES directly in the model field.

Hope this helps.

๐Ÿ‘คreczy

6๐Ÿ‘

I know you already accepted an answer but I just want to post this in case someone out there runs into the issue I was having, namely the accepted solution does not work with a ValueListQuerySet. The EmptyChoiceField, which you linked to, works perfectly for me (although I am using django 1.7).

class EmptyChoiceField(forms.ChoiceField):
    def __init__(self, choices=(), empty_label=None, required=True, widget=None, label=None, initial=None, help_text=None, *args, **kwargs):

        # prepend an empty label if it exists (and field is not required!)
        if not required and empty_label is not None:
            choices = tuple([(u'', empty_label)] + list(choices))

        super(EmptyChoiceField, self).__init__(choices=choices, required=required, widget=widget, label=label, initial=initial, help_text=help_text, *args, **kwargs) 

class FilterForm(forms.ModelForm):
    #place your other fields here 
    state = EmptyChoiceField(choices=People.objects.all().values_list("state", "state").distinct(), required=False, empty_label="Show All")
๐Ÿ‘คVT_Drew

2๐Ÿ‘

A little late to the party..

How about not modifying the choices at all and just handling it with a widget?

from django.db.models import BLANK_CHOICE_DASH

class EmptySelect(Select):
    empty_value = BLANK_CHOICE_DASH[0]
    empty_label = BLANK_CHOICE_DASH[1]

    @property
    def choices(self):
        yield (self.empty_value, self.empty_label,)
        for choice in self._choices:
            yield choice

    @choices.setter
    def choices(self, val):
        self._choices = val

Then just call it:

class SomeForm(forms.Form):
    # thing = forms.ModelChoiceField(queryset=Thing.objects.all(), empty_label='Label')
    color = forms.ChoiceField(choices=COLORS, widget=EmptySelect)
    year = forms.ChoiceField(choices=YEAR_CHOICES, widget=EmptySelect)

Naturally, the EmptySelect would be placed inside some kind of common/widgets.py code and then when ever you need it, just reference it.

๐Ÿ‘คJavier Buzzi

1๐Ÿ‘

Had to use 0 instead of uโ€ because of integer field in model. (Error was invalid literal for int() with base 10: โ€˜)

# prepend an empty label if it exists (and field is not required!)
if not required and empty_label is not None:
    choices = tuple([(0, empty_label)] + list(choices))
๐Ÿ‘คPat

1๐Ÿ‘

another way to achieve this is to define the select widget separately from the rest of the widgets and change the method of saving the content.

forms.py

class CardAddForm(forms.ModelForm):
    category = forms.ModelChoiceField(empty_label='Choose category',
                                      queryset=Categories.objects.all(),
                                      widget=forms.Select(attrs={'class':'select-css'}))

    class Meta:
        **other model field**

And in views.py you should use obj.create(**form.cleaned_data) instead form.save()

๐Ÿ‘คtype49

0๐Ÿ‘

It is not the same form, but I did it the following way inspired by the EmptyChoiceField method:

from django import forms
from ..models import Operator


def parent_operators():
    choices = Operator.objects.get_parent_operators().values_list('pk', 'name')
    choices = tuple([(u'', 'Is main Operator')] + list(choices))
    return choices


class OperatorForm(forms.ModelForm):
    class Meta:
        model = Operator
        # fields = '__all__'
        fields = ('name', 'abbr', 'parent', 'om_customer_id', 'om_customer_name', 'email', 'status')

    def __init__(self, *args, **kwargs):
        super(OperatorForm, self).__init__(*args, **kwargs)
        self.fields['name'].widget.attrs.update({'class': 'form-control m-input form-control-sm'})
        self.fields['abbr'].widget.attrs.update({'class': 'form-control m-input form-control-sm'})
        self.fields['parent'].widget.attrs.update({'class': 'form-control m-input form-control-sm'})
        self.fields['parent'].choices = parent_operators()
        self.fields['parent'].required = False
        self.fields['om_customer_id'].widget.attrs.update({'class': 'form-control m-input form-control-sm'})
        self.fields['om_customer_name'].widget.attrs.update({'class': 'form-control m-input form-control-sm'})
        self.fields['email'].widget.attrs.update({'class': 'form-control m-input form-control-sm', 'type': 'email'})enter code here
๐Ÿ‘คcwhisperer

0๐Ÿ‘

Add Empty String with 9 Hyphens to choices as shown below:

class DateForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        class Months(models.TextChoices):
            EMPTY_LABEL = '', '---------' # Here
            JANUARY = 'JAN', 'January'
            FEBRUARY = 'FEB', 'February'
            MARCH = 'MAR', 'March'
                                 
        self.fields['month'].choices = Months.choices

0๐Ÿ‘

Itโ€™s work for me
Django version 4.0.4

Group.objects.values_list()

from django.contrib.auth.models import Group
GROUP_CHOICES = [('','Select the Group')] + list(Group.objects.values_list())

groups = forms.ChoiceField(choices=GROUP_CHOICES, required=False)
๐Ÿ‘คGaurav Nagar

Leave a comment