This is pretty much related to this: How to access data when form.is_valid() is false
In my case, if the form validation fails, I'd like to have user view the same page with an error message AND have it to show a new and modified cleaned_data comment. Right now, if it fails the form validation, it'll show the page with old user submitted comment. The reason why I want to show the modified comment is because I want the new data to match the error message. For example, If an user submitted
' hey bye '
to get around the 20 character minimum limit, my cleaning function will strip the white spaces and trim it down to
'hey bye'
and then fail the validation. The error message will say "The comment length needs to be at least 20 characters long". With the old data, the user will get confused because he actually put in more than 20 characters and the old data will show it. I want them to see the stripped comment, so they will know why I failed it.
Here's my code...
views.py
def question(request, qid):
quest = shortcuts.get_object_or_404(askbox.models.Question, pk=qid)
log.info("Question #{0}: {1}".format(qid, quest))
user = SessionManager.getLoggedInUser(request)
answerForm = AnswerForm()
if request.method == "POST":
if user == None:
return HttpResponseRedirect(reverse('login.views.login'))
answerForm = AnswerForm(request.POST)
if answerForm.is_valid():
# user posted an answer
answerForm.question = quest
answerForm.user = user
answerForm.save()
return HttpResponseRedirect(reverse('question.views.question', args=(quest.id,)))
else:
#answerForm.text = answerForm.saved_data['text'] #doesn't work too
answerForm.text = "foo" # doesn't work...
else: # GET request
# landing page
# probably do nothing
pass
print "AnswerForm: {0}".format(answerForm)
mediaList = askbox.models.Media.objects.filter(question=qid)
return shortcuts.render_to_response('question/question.html', {
'title': 'Groupthink | {0}'.format(quest.question),
'css_list': css_list,
'js_list': js_list,
'question': quest,
'mediaList': mediaList,
'user': user,
'answerForm': answerForm,
}, context_instance=RequestContext(request))
forms.py
# fake abstract class...
class AbstractCommentForm(forms.ModelForm):
text = forms.CharField(min_length=MIN_ANSWER_LEN, max_length=MAX_ANSWER_LEN, widget=forms.Textarea) # the comment text
def clean_text(self):
# we want to avoid user cheating the system. We'll trim extra spaces between characters and then strip spaces at both ends of the string
field = 'text'
self.cleaned_data[field] = (re.sub(r' +', ' ', self.cleaned_data[field])).strip()
self.text = self.cleaned_data[field] # doesn't work
text_len = len(self.cleaned_data[field])
self.saved_data = self.cleaned_data # doesn't work
if text_len < MIN_ANSWER_LEN:
raise forms.ValidationError("The comment length needs to be at least {0} characters long".format(MIN_ANSWER_LEN))
if text_len > MAX_ANSWER_LEN:
raise forms.ValidationError("The comment length exceeds the maximum {0} characters".format(MAX_ANSWER_LEN))
return self.cleaned_data[field]
class CommentForm(AbstractCommentForm):
class Meta:
model = Comment
class AnswerForm(AbstractCommentForm):
class Meta:
model = Answer