23

I want to get rid of the "-------------" choice Django adds in a select input representing a Foreign Key on a ModelForm

It's been answered that you can use the empty_label=none option, but I have a ModelForm, not a regular form and overriding the field is not allowed.

I know that I can override the __init__() method of the ModelForm in order to modify a ModelChoiceField's queryset using

self.fields['my_foreign_key'].queryset = ....

But this would be really ugly, as this happens over +10 foreign_keys on the "Main" model, and there's more than a Modelform based on this model

The whole context :

  • each one of these foreign_key points to the same kind of models : they are particular lists of choices, many models to ease their modification via the admin.
  • all these models are related to the Main model via a "to_field=code" relation, based on a Charfield which contains a three-letter code (hey, not my fault, I had to use a legacy MS Access DB), this CharField has the blank=True, unique=True options, so I could, for each list, create a "---No information yet---" record which has, you bet, a blank value instead of a three letter code...

The situation is now : I get a select input field with two "blank value" choices : the django one and mine, one after the other. I just miss a 'empty_label=none` option here too...

Community
  • 1
  • 1
Dominique Guardiola
  • 3,431
  • 2
  • 22
  • 22
  • I think you can redefine/overwrite the field. I do this to change a DateTime model field into a forms TimeField (and add an extra field of DateField). Then I override the clean() method of the form to combine the date and time fields. – Matthew Schinckel Jan 15 '11 at 08:07

1 Answers1

42

If you want to remove the blank choice for all ModelChoiceField you could do something like..

class Form(forms.ModelForm):
    class Meta:
        model = MyModel

    def __init__(self, *args, **kwargs):
        super(Form, self).__init__(*args, **kwargs)
        modelchoicefields = [field for field_name, field in self.fields.iteritems() if
            isinstance(field, forms.ModelChoiceField)]

        for field in modelchoicefield:
            field.empty_label = None

But that would replace all ModelChoiceFields, so maybe something more fine grained like:

for fieldname in ('field1','field2','field3','field4','field5','field6'):
    self.fields[fieldname].empty_label = None

Certainly easier than the __init__ overwrite you mentioned!

Update from Moritz

You can use 2017+ use:

forms.ModelChoiceField(... empty_label=None
Yuji 'Tomita' Tomita
  • 115,817
  • 29
  • 282
  • 245