【问题标题】:How to raise a error inside form_valid method of a CreateView如何在 CreateView 的 form_valid 方法中引发错误
【发布时间】:2016-03-23 01:05:43
【问题描述】:

在一个 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))

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 声明可能会缩进一层以仅涵盖成功的案例。此外,取消缩进 return self.render_to_response 并删除 else 语句,看看是否有效。
  • 另一件事是,听起来您在调用form.is_valid 后尝试检查表单验证。但是我觉得还是用form.clean方法做比较好。

标签: python django django-views


【解决方案1】:

作为一般规则,模型验证应该进入模型字段验证器或模型的clean 方法。表单验证应该进入表单的cleanclean_&lt;field&gt; 方法。

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

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

【讨论】:

  • 我已经尝试过解决方案:return form_invalid。但它打破了我的形式。当再次呈现表单时,不会显示 UserForm。取而代之的是一个新的 IdeaFormset 实例,被翻了一番。
  • 看起来您在视图中也遇到了多个表单/表单集的问题,让我建议您进一步阅读stackoverflow.com/questions/34251412/…
  • 哇,谢谢你 x9999 次。我正在返回form_valid,但看不到错误,它也被重定向了。
  • 这是对 ABAP/4 做事方式的一种回归,在交易的每个阶段验证都非常容易。我需要一种方法来捕获用户输入,与现有值进行比较并进行验证 - 它满足了需求。
猜你喜欢
  • 2018-04-07
  • 2015-11-21
  • 1970-01-01
  • 2018-10-02
  • 1970-01-01
  • 1970-01-01
  • 2015-10-18
  • 1970-01-01
  • 2021-01-02
相关资源
最近更新 更多