Joseph
Joseph

Reputation: 13178

Dynamically alter Field choices in Django ModelForm

I have a field on a Model like so:

class MyModel(models.Model):
    status_field = models.NullBooleanField(blank=False,
                                          verbose_name="Status",
                                          choices=((True, 'Approved'),
                                                   (False, 'Denied'),
                                                   (None, 'Pending')))

I then have a ModelForm for this Model. In that ModelForm, I want to conditionally/dynamically remove one of these choices. I'm currently trying:

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

    def __init__(self, *args, **kwargs):
        super(MyModelForm, self).__init__(*args, **kwargs)


        if self.instance and self.instance.status_field is not None:
            self.fields['status_field'].choices.remove((None, 'Pending'))
            print self.fields['status_field'].choices

I can tell from the print statement that the choice is indeed removed. However, I must be missing something because when the form is rendered, the widget for this field still includes the choice I removed.

Effectively what I'm trying to do is prevent this field from becoming None/null once a value has been supplied. To make it easy for users, I'd like to just remove that option in the dropdown.

Thanks for the help!

Upvotes: 3

Views: 5301

Answers (1)

catavaran
catavaran

Reputation: 45575

Then the form is initialized the choices property is copied from the field to the field's widget. So you have to remove the choice from the widget too:

if self.instance and self.instance.status_field is not None:
    new_choices = list(self.fields['status_field'].choices)
    new_choices.remove((None, 'Pending'))
    self.fields['status_field'].choices = new_choices
    self.fields['status_field'].widget.choices = new_choices

Upvotes: 13

Related Questions