Reputation: 41665
Django form trips me many times...
I gave initial value to a ChoiceField (init of Form class)
self.fields['thread_type'] = forms.ChoiceField(choices=choices,
widget=forms.Select,
initial=thread_type)
The form which is created with thread_type
with the above code doesn't pass is_valid() because 'this field(thread_type) is required'.
-EDIT-
found the fix but it still perplexes me quite a bit.
I had a code in my template
{% if request.user.is_administrator() %}
<div class="select-post-type-div">
{{form.thread_type}}
</div>
{% endif %}
and when this form gets submitted, request.POST doesn't have 'thread_type' when user is not admin.
the view function creates the form with the following code:
form = forms.MyForm(request.POST, otherVar=otherVar)
I don't understand why giving initial value via the the following(the same as above) is not enough.
self.fields['thread_type'] = forms.ChoiceField(choices=choices,
widget=forms.Select,
initial=thread_type)
And, including the thread_type
variable in request.POST
allows the form to pass the is_valid() check.
The form class code looks like the following
class EditQuestionForm(PostAsSomeoneForm, PostPrivatelyForm):
title = TitleField()
tags = TagNamesField()
#some more fields.. but removed for brevity, thread_type isn't defined here
def __init__(self, *args, **kwargs):
"""populate EditQuestionForm with initial data"""
self.question = kwargs.pop('question')
self.user = kwargs.pop('user')#preserve for superclass
thread_type = kwargs.pop('thread_type', self.question.thread.thread_type)
revision = kwargs.pop('revision')
super(EditQuestionForm, self).__init__(*args, **kwargs)
#it is important to add this field dynamically
self.fields['thread_type'] = forms.ChoiceField(choices=choices, widget=forms.Select, initial=thread_type)
Upvotes: 3
Views: 1073
Reputation: 5257
Instead of adding this field dynamically, define it in the class appropriately:
class EditQuestionForm(PostAsSomeoneForm, PostPrivatelyForm):
title = TitleField()
tags = TagNamesField()
thread_type = forms.ChoiceField(choices=choices, widget=forms.Select)
When creating the form instance set an intitial value if needed:
form = EditQuestionForm(initial={'tread_type': thread_type})
And if you dont need this field, just delete it:
class EditQuestionForm(PostAsSomeoneForm, PostPrivatelyForm):
def __init__(self, *args, **kwargs):
super(EditQuestionForm, self).__init__(*args, **kwargs)
if some_condition:
del self.fields['thread_type']
When saving form, check:
thread_type = self.cleaned_data['thread_type'] if 'thread_type' in self.cleaned_data else None
This approach always works well for me.
Upvotes: 1