【问题标题】:Django Forms: if not valid, show form with error messageDjango Forms:如果无效,则显示带有错误消息的表单
【发布时间】:2013-01-16 20:23:15
【问题描述】:

在Django表单中,它可以检查表单是否有效:

if form.is_valid(): 
    return HttpResponseRedirect('/thanks/')

但是我错过了如果它无效该怎么办?如何返回带有错误消息的表单?我在任何示例中都没有看到“else”。

【问题讨论】:

    标签: django django-forms


    【解决方案1】:

    如果您在表单无效时呈现相同的视图,那么在模板中您可以access the form errors using form.errors

    {% if form.errors %}
        {% for field in form %}
            {% for error in field.errors %}
                <div class="alert alert-danger">
                    <strong>{{ error|escape }}</strong>
                </div>
            {% endfor %}
        {% endfor %}
        {% for error in form.non_field_errors %}
            <div class="alert alert-danger">
                <strong>{{ error|escape }}</strong>
            </div>
        {% endfor %}
    {% endif %}
    

    一个例子:

    def myView(request):
        form = myForm(request.POST or None, request.FILES or None)
        if request.method == 'POST':
            if form.is_valid():
                return HttpResponseRedirect('/thanks/')
        return render(request, 'my_template.html', {'form': form})
    

    【讨论】:

    • 我添加了一个简单的例子。确保您遵循我提到的相同方法。
    • 我明白了。我返回的表单与我输入的相同。错误消息已由 is_valid() 函数自动添加到其中。
    • 是的,您现在就知道了。如果您没有手动呈现表单,则会自动为每个字段显示错误。
    • @AlexanderSupertramp myFormforms.Formforms.ModelForm 的一个实例,了解Django Forms
    • 如果我没有视图怎么办......例如使用 CMS 中的标准管理表单。例如UNIQUE constraint failed: 异常?
    【解决方案2】:

    views.py

    from django.contrib import messages 
    
    def view_name(request):
        if request.method == 'POST':
            form = form_class(request.POST)
            if form.is_valid():
                return HttpResponseRedirect('/thanks'/)
            else:
                messages.error(request, "Error")
    return render(request, 'page.html', {'form':form_class()})
    

    如果您想显示表单的错误而不是无效的,只需像我在下面所做的那样输入 {{form.as_p}}

    page.html

    <html>
        <head>
            <script>
                {% if messages %}
                    {% for message in messages %}
                        alert('{{message}}')
                    {% endfor %}
                {% endif %}
            </script>
        </head>
        <body>
            {{form.as_p}}
        </body>
    </html> 
    

    【讨论】:

    • 然后我返回什么?这如何进入我的模板?
    • 我更新了我的代码。如果需要,您还可以将 for 循环消息放在模板中而不是脚本中。
    • 这是一个很酷的方法 - 但需要警惕('{{message}}');
    • 您如何在视图中的错误消息中添加比 messages.error(request, "Error") 所做的“错误”更具描述性的内容?
    【解决方案3】:

    更新: 添加了更详细的表单集错误描述。


    Form.errors 结合了所有字段和非字段错误。因此,您可以将 html 简化为:

    模板

        {% load form_tags %}
    
        {% if form.errors %}
        <div class="alert alert-danger alert-dismissible col-12 mx-1" role="alert">
            <div id="form_errors">
                {% for key, value in form.errors.items %}
                    <span class="fieldWrapper">
                        {{ key }}:{{ value }}
                    </span>
                {% endfor %}
            </div>
            <button type="button" class="close" data-dismiss="alert" aria-label="Close">
                <span aria-hidden="true">&times;</span>
            </button>
        </div>
        {% endif %}
    
    
    If you want to generalise it you can create a list_errors.html which you include in every form template. It handles form and formset errors:
    
        {% if form.errors %}
        <div class="alert alert-danger alert-dismissible col-12 mx-1" role="alert">
            <div id="form_errors">
    
                {% for key, value in form.errors.items %}
                    <span class="fieldWrapper">
                        {{ key }}:{{ value }}
                    </span>
                {% endfor %}
            </div>
            <button type="button" class="close" data-dismiss="alert" aria-label="Close">
                <span aria-hidden="true">&times;</span>
            </button>
        </div>
        {% elif formset.total_error_count %}
        <div class="alert alert-danger alert-dismissible col-12 mx-1" role="alert">
            <div id="form_errors">
                {% if formset.non_form_errors %}
                    {{ formset.non_form_errors }}
                {% endif %}
                {% for form in formset.forms %}
                    {% if form.errors %}
                        Form number {{ forloop.counter }}:
                        <ul class="errorlist">
                        {% for key, error in form.errors.items %}
                            <li>{{form.fields|get_label:key}}
                                <ul class="errorlist">
                                    <li>{{error}}</li>
                                </ul>
                            </li>
                        {% endfor %}
                        </ul>
                    {% endif %}
                {% endfor %}
    
            </div>
        </div>
    
        {% endif %}
    

    form_tags.py

    from django import template
    
    register = template.Library()
    
    
    def get_label(a_dict, key):
        return getattr(a_dict.get(key), 'label', 'No label')
    
    
    register.filter("get_label", get_label)
    
    

    一个警告:与表单相比,Formset.errors 不包括 non_field_errors。

    【讨论】:

      【解决方案4】:
      def some_view(request):
          if request.method == 'POST':
              form = SomeForm(request.POST)
              if form.is_valid():
                  return HttpResponseRedirect('/thanks'/)
          else:
              form = SomeForm()
          return render(request, 'some_form.html', {'form': form})
      

      【讨论】:

      • 这太美了!感谢分享。我曾经在 if 语句之前创建实例,它不会从 if 语句中捕获错误。
      【解决方案5】:

      This answer 正确但有一个问题:未定义字段。 如果您有多个字段,则无法识别哪个字段有错误。

      通过此更改,您可以显示字段名称:

      {% if form.errors %}
          {% for field in form %}
              {% for error in field.errors %}
                  <div class="alert alert-danger">
                      <strong>{{ field.label }}</strong><span>{{ error|escape }}</strong>
                  </div>
              {% endfor %}
          {% endfor %}
          {% for error in form.non_field_errors %}
              <div class="alert alert-danger">
                  <strong>{{ error|escape }}</strong>
              </div>
          {% endfor %}
      {% endif %}
       
      

      【讨论】:

        【解决方案6】:

        @AamirAdnan 的答案缺少field.label;另一种以几行显示错误的方式。

        {% if form.errors %}
            <!-- Error messaging -->
            <div id="errors">
                <div class="inner">
                    <p>There were some errors in the information you entered. Please correct the following:</p>
                    <ul>
                        {% for field in form %}
                            {% if field.errors %}<li>{{ field.label }}: {{ field.errors|striptags }}</li>{% endif %}
                        {% endfor %}
                    </ul>
                </div>
            </div>
            <!-- /Error messaging -->
        {% endif %}
        

        【讨论】:

        • striptags 过滤器正是我所需要的——感谢分享。
        【解决方案7】:

        您可以这样做,因为当您初始化表单时,还包含表单数据和无效数据:

        def some_func(request):
            form = MyForm(request.POST)
            if form.is_valid():
                 //other stuff
            return render(request,template_name,{'form':form})
        

        如果模板中有错误,则会在模板中引发错误,但表单数据仍将保持为:

        error_demo_here

        【讨论】:

          【解决方案8】:

          您可以简单地放置一个标志变量,在本例中为 is_successed

          def preorder_view(request, pk, template_name='preorders/preorder_form.html'):
              is_successed=0
              formset = PreorderHasProductsForm(request.POST)
              client= get_object_or_404(Client, pk=pk)
              if request.method=='POST':
                  #populate the form with data from the request
                 # formset = PreorderHasProductsForm(request.POST)
                  if formset.is_valid():
                      is_successed=1
                      preorder_date=formset.cleaned_data['preorder_date']
                      product=formset.cleaned_data['preorder_has_products']
                      return render(request, template_name, {'preorder_date':preorder_date,'product':product,'is_successed':is_successed,'formset':formset})
          
          
          
              return render(request, template_name, {'object':client,'formset':formset})
          

          然后在您的模板中,您可以将代码放在下面

          {%if is_successed == 1 %}
          <h1>{{preorder_date}}</h1>
          <h2> {{product}}</h2>
          {%endif %}
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2013-09-27
            • 2020-10-25
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-09-12
            • 1970-01-01
            相关资源
            最近更新 更多