Override ChoiceField widget in Django ModelForm without re-specifying choices

django, django-forms, django-models

Solution

I think the reason you are losing the choices you specified in your model i.e. "sets it to `[]`" is not "because Django", but because you override the icon field with the line `icon = models.ChoiceField(widget=IconPicker)`

Please note that if you are using a modelform then it is not necessary to override the widget at init, instead the widget should be specified in the Meta class in the widgets dictionary.

class UserGroupForm(forms.ModelForm):

    class Meta:
        model = UserGroup
        fields = [ 'icon', ]
        widgets = {
            'icon': IconPicker
        }

As for overriding the choices you can simply do `self.fields['icon'].choices = UserGroupForm.ICON_CHOICES`, but I don't think you need to override choices in this instance.

Problem

I am trying to override the default widget for a Django `ChoiceField` while preserving the choices generated in the model. Here is the relevant part of my model: ``` class UserGroup(models.Model): icon = models.CharField(max_length=100, choices=<function call>) ``` And of my form: ``` class UserGroupForm(forms.ModelForm): icon = models.ChoiceField(widget=IconPicker) class Meta: model = UserGroup fields = [ 'icon', ] ``` Overriding the `ChoiceField`'s widget like this clobbers the `form.fields['icon'].choices` attribute normally inherited from the model and sets it to `[]` because Django. If I remove the `icon` field definition from the form, the choices are preserved - but of course the widget defaults to a `Select`. (The function which generates the choices for the model field is not accessible from the form code unfortunately.) The best I have come up with so far for is to change the `icon` form field definition to ``` icon = ChoiceField(choices=UserGroup._meta.get_field_by_name('icon')[0].choices, widget=IconPicker) ``` but this is clunky and I would rather have the choices automatically passed on as in the introspected `ChoiceField` behavior. (I tried subclassing `ChoiceField` to `IconChoiceField` which was identical but for a default widget of `IconPicker` but Django converts it back to a `TypedChoiceField` with the default `Select` widget because of this issue.) Is there a way to override the `ChoiceField`'s `widget` attribute while preserving the behavior of inheriting `choices` from the model?

Original source