如何在CreateView的form_valid方法中引发错误

Raf*_*ael 8 python django django-views

在Django项目中,我有一个视图(云),类型:CreateView.此视图具有inlineformset_factory.有用.但是,如果我提交带有错误的表单(请查看下面的"messages.error"),页面将重定向到project.get_absolute_url().问题是:表单内容回空.我知道那是因为HttpResponseRedirect.

如何在不破坏表格的情况下更改此内容?

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))
Run Code Online (Sandbox Code Playgroud)

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>
Run Code Online (Sandbox Code Playgroud)

Lor*_*eña 28

作为一般规则,模型验证应该进入模型字段验证器或模型的clean方法.表格验证应该采用表格cleanclean_<field>方法.

如果你需要验证视图中的内容form_valid,你可以使用form.add_error然后,而不是重定向(或返回super(cloud, self).form_valid(form),无论如何重定向),你可以返回super(cloud, self).form_invalid(form).

检查:https: //docs.djangoproject.com/en/1.9/ref/forms/api/#django.forms.Form.add_error

  • 看来您在视图中还存在多个表单/表单集问题,让我建议您进一步阅读http://stackoverflow.com/questions/34251412/how-to-validate-mulitple-forms-in-一个-单一表单视图类-Django / 34275307#34275307 (2认同)