How to change empty_label for modelForm choice field?

dokkaebi, that won't work properly. You'll receive the following select code:

<select name="payrollProvider" id="id_payrollProvider">
<option value="" selected="selected">---------</option>
<option value="" selected="selected">please choose value</option>
<option value="C1">Choice1</option>
<option value="C2">Choice2</option>
</select>

The only relatively convenient way that came to my mind is to do something like this in the form:

class PayrollCredentialForm(forms.ModelForm):
    class Meta:
        model = Company
    def __init__(self, *args, **kwargs):
        super(PayrollCredentialForm, self).__init__(*args, **kwargs)
        self.fields["payrollProvider"].choices = [("", "please choose value"),] + list(self.fields["payrollProvider"].choices)[1:] 

The problem is that you are trying to specify something that is not available for the type of Select field.

The empty_label option is for forms.ModelChoiceField, which happens to use a Select widget, but is not the same kind of field as your CharField that you are providing options for.

https://docs.djangoproject.com/en/dev/ref/forms/fields/#modelchoicefield

You can see this also in a previous question here: https://stackoverflow.com/a/740011/1406860

You could try and override the html of the modelform to add the first option as "please choose value". Alternatively, you could use a template filter to do the same thing. Lastly, you could and ("", "please choose value") to PAYROLL_CHOICES, and if you don't want it to be submitted without a payrollProvider just set blank=False for the field in the model.

JD


Actually, now (as of Django 1.8 and higher) override of an empty_label works:

class PayrollCredentialForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(PayrollCredentialForm, self).__init__(*args, **kwargs)
        self.fields['payrollProvider'].empty_label = 'Please, choose value'

Also, if you working with Django Admin, there is an option to set empty value for a list view:

class PayrollCredentialAdmin(admin.ModelAdmin):
    list_display = ('payrollProvider_value', )

    def payrollProvider_value(self, instance):
        return instance.payrollProvider
    payrollProvider_value.empty_value_display = 'Empty value'

What if field should be readonly?

There is a catch if field modified in such way should be readonly.

If overridden form field will be specified in readonly_fields attribute inside PayrollCredentialAdmin class, it would result in KeyError exception in PayrollCredentialForm (because readonly field won't be included in form's self.fields). To handle that, it's required to override formfield_for_dbfield instead of using readonly_fields:

def formfield_for_dbfield(self, db_field, **kwargs):
    field = super(PayrollCredentialAdmin, self).formfield_for_dbfield(
        db_field, **kwargs
    )
    db_fieldname = canonical_fieldname(db_field)

    if db_fieldname == 'payrollProvider':
        field.widget = forms.Select(attrs={
            'readonly': True, 'disabled': 'disabled',
        })

    return field

Might be useful.


Update for Django 1.11:

Comments below brought assumption that such override is no longer valid for newer version of Django.