【问题标题】:Django Validation Error raised but not displayed for shopping cart appDjango 验证错误引发但未显示在购物车应用程序中
【发布时间】:2019-10-07 11:47:02
【问题描述】:

我正在运行 Django 2.2 并编写了一个简单的购物车。我希望同时验证两个字段,这样两个字段不能同时为空。在我的 forms.py 中,

from django import forms

class CartAddProductForm(forms.Form):
    cc_handle = forms.CharField(required=False, label='CC Handle', empty_value='')
    lc_handle = forms.CharField(required=False, label='LC Handle', empty_value='')

    def clean(self):
        cleaned_data = super().clean()
        if cleaned_data.get('cc_handle') == '' and cleaned_data.get('lc_handle') == '':
            print("issue detected")
            raise forms.ValidationError('Either cc or lc handle is required.')
        return cleaned_data

这是按照官方Django docs 对相互依赖的字段进行清理和验证。上面的 print() 语句让我知道问题已被检测到,即两个字段都是空的。运行 Django 服务器,我看到确实检测到了问题,但原始页面顶部没有显示验证错误消息。原始页面是包含产品和将产品添加到购物车的链接的产品页面。通常验证错误消息会显示在页面顶部。

根据文档,验证是在调用 is_valid() 时完成的。所以我把我的views.py的诊断打印出来了

from django.shortcuts import render, redirect, get_object_or_404
from django.views.decorators.http import require_POST
from shop.models import Product
from .cart import Cart
from .forms import CartAddProductForm

@require_POST
def cart_add(request, product_id):
    cart = Cart(request)
    product = get_object_or_404(Product, id=product_id)
    form = CartAddProductForm(request.POST)
    if form.is_valid():
        cd = form.cleaned_data
        cart.add(product=product,
                cc_handle=cd['cc_handle'],
                lc_handle=cd['lc_handle'])
    else:
        print('invalid form')
    return redirect('cart:cart_detail')

确实弹出了“无效形式”一词。然后代码将我带到购物车。相反,我想要的是在产品页面上显示验证错误,通知读者这两个字段不能为空。有没有简单的方法?

对于表单中的 required=True 字段,如果我将其留空,则会弹出一条消息说我需要填写它。所以我想做类似的事情,除了验证要求两个字段都不能空的。

这与Stackoverflow answer 不同,因为那是一个注册表单。您可以将其重定向到相同的表单,而对于这种情况,CartAddProductForm 嵌入在站点上的所有产品页面中。如果可能,我希望验证与 required=True 选项的字段在同一阶段进行。

product/detail.html 模板如下所示。

{% extends "shop/base.html" %}
{% load static %}

{% block title %}
{{ product.name }}
{% endblock %}

{% block content %}
<div class="product-detail">
    <img src="{% if product.image %}{{ product.image.url }}{% else %}{% static "img/no_image.png" %}{% endif %}">
    <h1>{{ product.name }}</h1>
    <h2><a href="{{ product.category.get_absolute_url }}">{{ product.category }}</a></h2>
    <p class="price">${{ product.price }}</p>
    <form action="{% url "cart:cart_add" product.id %}" method="post">
    {{ cart_product_form }}
    {% csrf_token %}
    <input type="submit" value="Add to cart">
    </form>
    {{ product.description|linebreaks }}
</div>
{% endblock %}

【问题讨论】:

  • 希望this 会有所帮助。你的form 模板看起来怎么样?
  • 嗯,这与您展示的帖子不同。在那里,您有一个注册表单,因此您可以重定向回它。我有多个产品,每个产品都嵌入了 CartAddProductForm。
  • {{ form }} 是如何呈现的?您可以添加form.html 有问题的代码吗?
  • 试试.add_errors() 方法。检查.non_field_errors() 是否出现任何错误。

标签: python django django-forms


【解决方案1】:

在表单模板中添加此行已解决您的问题。

{{ cart_product_form.non_field_errors }}

product/detail.html:

{% extends "shop/base.html" %}
{% load static %}

{% block title %}
{{ product.name }}
{% endblock %}

{% block content %}
<div class="product-detail">
    <img src="{% if product.image %}{{ product.image.url }}{% else %}{% static "img/no_image.png" %}{% endif %}">
    <h1>{{ product.name }}</h1>
    <h2><a href="{{ product.category.get_absolute_url }}">{{ product.category }}</a></h2>
    <p class="price">${{ product.price }}</p>
    <form action="{% url "cart:cart_add" product.id %}" method="post">
    {{ cart_product_form }}
    {% csrf_token %}
    {{ cart_product_form.non_field_errors }} // This line will raise validation errors
    <input type="submit" value="Add to cart">
    </form>
    {{ product.description|linebreaks }}
</div>
{% endblock %}

文档:(抄自官方文档)

请注意,您的 Form.clean() 覆盖引发的任何错误都不会 特别与任何领域相关联。他们进入一个特殊的 “field”(称为all),您可以通过 如果需要,可以使用 non_field_errors() 方法。如果要附加错误 对于表单中的特定字段,您需要调用 add_error()。

【讨论】:

    【解决方案2】:

    您的视图无条件地重定向到cart_details,因此您看不到验证错误也就不足为奇了——您必须为此呈现无效的表单。您应该只在帖子成功时重定向。

    【讨论】:

    • 是的,我知道。这就是诊断 print() 所显示的内容。
    • 恐怕你没有明白这一点:如果你不渲染表单并把它扔掉,你如何期望验证错误出现??? 你认为它们会自动在以太中的某个地方存活并在下一个 GET 请求中重新出现吗???
    • 没有必要让所有的工作和无礼。我正在寻找一种解决方案,该解决方案在不允许表单发布的情况下进行验证,这是在设置 required=True 时所做的。现在看来,这是不可能的。我愿意接受有关如何最好地为下一个 GET 请求保留错误消息的建议。上面发布的代码是我们知道的代码的当前状态不起作用。
    猜你喜欢
    • 1970-01-01
    • 2012-11-16
    • 2015-11-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-04
    • 1970-01-01
    • 1970-01-01
    • 2016-03-30
    相关资源
    最近更新 更多