In a Django project, I have a view (cloud), type: CreateView. This view has a inlineformset_factory. It works. But, if i submit the form with a error (look at "messages.error" below), the page is redirected to project.get_absolute_url(). The problem is: the form content back empty. I know thats because the HttpResponseRedirect.
How can I change this without to break the form?
views.py
class cloud(CreateView):
template_name = 'base/cloud.html'
form_class = UserForm
def get_context_data(self, **kwargs):
context = super(cloud, self).get_context_data(**kwargs)
project = get_object_or_404(Project, slug=self.kwargs['slug'])
context['project'] = project
if self.request.POST:
context['formset'] = IdeaFormset(self.request.POST or None)
else:
context['formset'] = IdeaFormset()
return context
def form_valid(self, form, **kwargs):
project = get_object_or_404(Project, slug=self.kwargs['slug'])
context = self.get_context_data()
formset = context['formset']
if formset.is_valid():
self.object = form.save()
formset.instance = self.object #IdeaFormFormSet
nouns = project.nouns().values_list('content', flat=True)
verbs = project.verbs().values_list('content', flat=True)
error = False
for form in formset.forms: #For each Idea
form.instance.project = project
if form.instance.sentence:
sentence = form.instance.sentence
validate_noun = [word for word in sentence.lower().split() if word in nouns]
validate_verbs = [word for word in sentence.lower().split() if word in verbs]
if (len(validate_noun) < 1):
error = True
messages.error(self.request, u'No noun was inserted into the sentence.', 'danger')
if (len(validate_verbs) < 1):
error = True
messages.error(self.request, u'No verb was inserted into the sentence.', 'danger')
if not error:
formset.save()
messages.success(self.request, u'Success!')
return HttpResponseRedirect( project.get_absolute_url() )
else:
return self.render_to_response(self.get_context_data(form=form))
cloud.html
<form role="form" method="post">
{% csrf_token %}
<legend>Ideas</legend>
<div class="panel-group" id="accordion" role="tablist" aria-multiselectable="true">
{% for idea_form in formset %}
{# Include the hidden fields #}
{% for hidden in idea_form.hidden_fields %}
{{ hidden }}
{% endfor %}
<div class="panel panel-default">
<div class="panel-heading" role="tab" id="heading_{{ forloop.counter }}">
<h4 class="panel-title">
<a {% if not forloop.first %} class="collapsed" {% endif %}
data-toggle="collapse" data-parent="#accordion" href="#collapse_{{ forloop.counter }}" aria-expanded="{{ forloop.first }}" aria-controls="collapse_{{ forloop.counter }}">
Idea #{{ forloop.counter }}
</a>
</h4>
</div>
<div id="collapse_{{ forloop.counter }}" class="panel-collapse collapse {% if forloop.first %} in {% endif %}" role="tabpanel" aria-labelledby="heading_{{ forloop.counter }}">
<div class="panel-body form-group" id="idea_{{ forloop.counter }}">
<div class="container-fluid">
{% for field in idea_form.visible_fields %}
<div class="row">
{{ field.errors }}
{{ field.label_tag }} {{ field }}
<span class="help-block">{{ field.help_text }}</span>
</div>
{% endfor %}
</div> <!--container-fluid-->
</div>
</div>
</div>
{% endfor %}
</div>
<legend>User</legend>
{% for field in form %}
<div class="form-group has-error">
{{ field.label_tag }} {{ field }}
{% if field.help_text %}
<p class="help-inline"><small>{{ field.help_text }}</small></p>
{% endif %}
<div class="help-block with-errors">
<span class="help-block">
{% for error in field.errors %}{{ error }}{% endfor %}
</span>
</div>
</div>
{% endfor %}
{{ formset.management_form }}
<div class="form-actions">
<button type="submit" class="btn btn-primary">Send!</button>
</div>
</form>
return HttpResonseRedirect
statement might indent one more level to cover only successful case. Also, unindent thereturn self.render_to_response
and removeelse
statement and see if that works. – Chalazaform.is_valid
is called. But I think it's better to do it inform.clean
method. – Chalaza