Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Customize/remove Django select box blank option

Haven't tested this, but based on reading Django's code here and here I believe it should work:

class ThingForm(models.ModelForm):
  class Meta:
    model = Thing

  def __init__(self, *args, **kwargs):
    super(ThingForm, self).__init__(*args, **kwargs)
    self.fields['verb'].empty_label = None

EDIT: This is documented, though you wouldn't necessarily know to look for ModelChoiceField if you're working with an auto-generated ModelForm.

EDIT: As jlpp notes in his answer, this isn't complete - you have to re-assign the choices to the widgets after changing the empty_label attribute. Since that's a bit hacky, the other option that might be easier to understand is just overriding the entire ModelChoiceField:

class ThingForm(models.ModelForm):
  verb = ModelChoiceField(Verb.objects.all(), empty_label=None)

  class Meta:
    model = Thing

from the docs

The blank choice will not be included if the model field has blank=False and an explicit default value (the default value will be initially selected instead).

so set the default and you're ok


With Carl's answer as a guide and after rooting around the Django source for a couple hours I think this is the complete solution:

  1. To remove the empty option (extending Carl's example):

    class ThingForm(models.ModelForm):
      class Meta:
        model = Thing
    
      def __init__(self, *args, **kwargs):
        super(ThingForm, self).__init__(*args, **kwargs)
        self.fields['verb'].empty_label = None
        # following line needed to refresh widget copy of choice list
        self.fields['verb'].widget.choices =
          self.fields['verb'].choices
    
  2. To customize the empty option label is essentially the same:

    class ThingForm(models.ModelForm):
      class Meta:
        model = Thing
    
      def __init__(self, *args, **kwargs):
        super(ThingForm, self).__init__(*args, **kwargs)
        self.fields['verb'].empty_label = "Select a Verb"
        # following line needed to refresh widget copy of choice list
        self.fields['verb'].widget.choices =
          self.fields['verb'].choices
    

I think this approach applies to all scenarios where ModelChoiceFields are rendered as HTML but I'm not positive. I found that when these fields are initialized, their choices are passed to the Select widget (see django.forms.fields.ChoiceField._set_choices). Setting the empty_label after initialization does not refresh the Select widget's list of choices. I'm not familiar enough with Django to know if this should be considered a bug.


You can use this on your model:

class MyModel(models.Model):
    name = CharField('fieldname', max_length=10, default=None)

default=None is the answer :D

NOTE: I tried this on Django 1.7


As for the django 1.4 all you need is to set the "default" value and "blank=False" on the choices field

class MyModel(models.Model):
    CHOICES = (
        (0, 'A'), 
        (1, 'B'),
    )
    choice_field = models.IntegerField(choices=CHOICES, blank=False, default=0)

you can do this in admin:

formfield_overrides = {
    models.ForeignKey: {'empty_label': None},
}