Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot validate dynamic choices with Django ModelForm

I have a Django ModelForm in Google App Engine with a ChoiceField, let's say location:

class MyForm(ModelForm):
    location = ChoiceField(label="Location")

    class Meta:
        model = MyModel

In order to dynamically add the choices for location, and not have issues with app caching, I add them after the form has initialized:

form = MyForm(request.POST, instance=my_instance)
form.fields['location'].choices = Location.all().fetch(1000)

The problem I'm having now is that when the form is initialized via the data in request.POST the choices do not yet exist and I am receiving an error stating that an invalid choice is made (since the value does not yet exist in the list of choices).

I don't like that validation is occurring when I am initializing the form instead of waiting until I call form.is_valid(). Is there any way to suppress validation during my object instantiation? Or some other way to fix this?

UPDATE: I'm pretty sure ModelFormMetaclass is causing me my grief by validating the provided instance when the form is created. Still not sure how to fix though.

Thanks!

like image 836
Chris Daviduik Avatar asked Oct 11 '25 08:10

Chris Daviduik


1 Answers

There must be other ways to do this, but possibly the most straightforward is to add the field in the form's __init__() method:

class MyForm(ModelForm):
    ...
    def __init__(self, *args, **kwargs):
        try:
            dynamic_choices = kwargs.pop('dynamic_choices')
        except KeyError:
            dynamic_choices = None # if normal form
        super(MyForm, self).__init__(*args, **kwargs)
        if dynamic_choices is not None:
            self.fields['location'] = ModelChoiceField(
                                          queryset=dynamic_choices)
    class Meta:
        model = MyModel

And your view would look something like:

def my_view(request):
    locations = Location.objects.all() # or filter(...) or whatever
    dynamic_form = MyForm(dynamic_choices=locations)

    return direct_to_template(request, 
                              'some_page.html',
                              {'form': dynamic_form},)

Let us know how that works for you.

like image 78
mechanical_meat Avatar answered Oct 14 '25 05:10

mechanical_meat



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!