django ModelForm form validation failing new entry


I have a django ModelForm called AdditionalDealSetupForm with the following code:

The problem is that when the form gets instantiated its failing validation implicitly being called by django.

The values that are being passed in the request object’s QueryDict look like this:

You can see above that the underwriters':['1','2','test4'] are the options and the 1, 2 are the id’s of existing underwriter objects while the ‘test4’ is a new item coming from the form. I am saving this test4 object to the db before the form gets checked right after the POST request comes in.

This form validation that fails is happening before the code explicitly calls is_valid() on the form.

<th><label for="id_underwriters">Underwriter(s):</label></th>
  **<ul class="errorlist"><li>“test4” is not a valid value.</li></ul>**

How can I get the form to pass validation ?

Check the html being rendered for these widgets. The value clause should be the PK of that model while the display value should be the output of the __str__ method.
What is being rendered for these entries?

Are you doing anything with a custom default manager or using a non-integer PK in the Underwriters model?

You can also see that if I override the clean() method within my form class, its being called after the html is being validated.

Use your browser’s developer’s tools to look at the HTML as it exists in the browser.

You want to look at what has been rendered and sent by the server.

(There are other ways of doing this, but this is the easiest.)

This is how its being rendered:

So you can see the value= clauses in the individual options - those are what should be submitted when the form is posted.

What does the view look like for this?

Also, the network tab of the developer tools will show what’s being submitted by the form. It’s worth looking at that to verify what data is being submitted.

In short, something, somewhere along the line is trying to manipulate these selections by the display value and not the pk.

Do you have any JavaScript involved with this widget?

Looking at what you’ve posted more closely, it looks like you may have Select2 involved here? (Am I reading that correctly?)

So keep in mind those value="11" clauses are for existing keys in the backend db already. I am trying to submit the form to allow for new key entry.

Ok, that’s the problem. You’re not going to be able to do that with this widget. The value must be the primary key of the entry. You’d need to submit the desired new entry as an AJAX call, re-render that widget with the new set of entries, and replace the existing widget with the new one returned by the server.

(You’d also have the option of creating a custom widget that would process the values as supplied in a different manner than how the standard widget works.)

1 Like

Interesting ok just so I understand you are saying that the form.SelectMultiple widget on the form field will not allow for the submission/validation of new values that are not already in the db model?

Not quite correct, it’s the form.ModelMultipleChoiceField that won’t allow it. (Yes, I was wrong by referencing it as the widget being the issue instead of it being the form field). That field validates the entries based on the value attribute being valid entries of the queryset being used for the widget.

1 Like

Interesting ok thats good to know thank you for your time and analysis here Ken.

Do you know where in the django docs it outlines that form. ModelMultipleChoiceField does not allow for newly typed values to be validated?

Also, do you know the form type that would allow this?

Directly from the docs for ModelMultipleChoiceField:

  • Validates that every id in the given list of values exists in the queryset.

None that I know of, and hopefully none at all. (We consider that type of structure to be an anti-pattern.)

Notice how the Django Admin puts a “+” sign with related fields to allow for the entry of additional data. You can’t just add data within the widget itself.

1 Like