【问题标题】:form.cleaned_data returns empty setform.cleaned_data 返回空集
【发布时间】:2015-07-04 08:58:06
【问题描述】:

我有一个表格:

class OrderForm(forms.Form):
    delivery_time = models.CharField(max_length=100)
    address_city = models.CharField(max_length=40)
    address_street = models.CharField(max_length=40)
    address_building = models.CharField(max_length=40)

这是我的看法:

def submit(request):
    args = {}
    args['form'] = OrderForm()
    if request.POST:
        order_form = OrderForm(request.POST)
        if order_form.is_valid():
            user = request.user
            address_city = order_form.cleaned_data.get('address_city')
            address_street = order_form.cleaned_data.get('address_street')
            address_building = order_form.cleaned_data.get('address_building')
            delivery_time = order_form.cleaned_data.get('delivery_time')
            new_order = Order(address_city=address_city,
                              address_street=address_street,
                              address_building=address_building,
                              delivery_date=delivery_time, client=user)
            new_order.save()
            Basket.objects.filter(client=user).delete()
            return redirect('/order/')
        else:
            args['form'] = order_form
    else:
        return render(request, 'order_page.html', args)

我猜这个问题出在我的模板上:

<form class="form-horizontal" action="{% url 'order_submit' %}" method="post">
        {% csrf_token %}   
        <div class="control-group">
            <label class="control-label" for="address">City<sup>*</sup></label>
            <div class="controls">
                <input type="text" id="address" placeholder="City name" name="address_city">
            </div>
        </div>

        ...

我想问题在于我不只使用{{form}}。但我需要这些样式形成我的表单。我对我的注册模板做同样的事情,它可以工作。注册表单继承UserCreationForm并与User模型绑定,但我的OrderForm继承form.Form。会是什么?

Order model:
class Order(models.Model):
    state_choices = ('ACTIVE', 'COMPLETED', 'FROZEN')
    order_date = models.DateTimeField(auto_now_add=True)
    delivery_time = models.CharField(max_length=100)
    address_city = models.CharField(max_length=40)
    address_street = models.CharField(max_length=40)
    address_building = models.CharField(max_length=40)
    state = models.CharField(max_length=200, default='ACTIVE')
    client = models.ForeignKey(CustomUser)

【问题讨论】:

  • 将打印语句或日志记录添加到您的视图以查看表单是否有效。如果不是,请检查 order_form.errors 包含的内容。
  • 调试时order_form.is_valid()返回True,order_form.errors为空
  • @Andrew 您可以指定通过Meta.fields 对用户可见的字段。 docs.djangoproject.com/en/1.8/topics/forms/modelforms
  • @andrew,您可以提供 request.user 作为模型表单的初始值,例如:OrderForm(initial={'client': request.user}, data=request.POST) docs.djangoproject.com/en/1.8/topics/forms/modelforms/…
  • 如果你想将逻辑保留在默认的 Django 表单中,你需要从forms.CharField(max=123)而不是models.CharField(max=123)构建字段。更改后,您应该会看到 {{ form }} 打印出表单并可以检查其标记以创建您自己的。

标签: django forms django-models django-forms


【解决方案1】:

您不应创建form.Form 类来显式处理每个字段。您可以改为从forms.ModelForm 继承并让模型表单为您处理一切。

sthzg 已经指出了问题,但是我仍然坚持您尽可能使用模型形式而不是普通形式。

这是您的表单类和视图的重写版本:

forms.py

class OrderForm(forms.ModelForm):
    class Meta:
        model = Order
        exclude = ['order_date', 'client', 'state']

views.py

def submit(request):
    if request.method == 'POST':
        form = OrderForm(initial={'client': request.user}, data=request.POST)
        if form.is_valid():
            order = form.save(commit=False)
            order.client = request.user
            order.save()
            Basket.objects.filter(client=request.user).delete()
            return redirect('/order/')
        else:
            return render(request, 'order_page.html', {'form': form})
    else:
        return render(request, 'order_page.html', {'form': OrderForm()})

【讨论】:

  • +1,这是更好的选择。一旦你让它与 ModelForm 一起工作,请检查 @ozgur 的答案是否正确。
  • 谢谢)你知道为什么当我按照你所说的初始时它为客户返回 null 吗?
  • 因为初始值不会作为新创建对象的属性值传递。它们用于form.is_valid() 返回True(尤其是在client 是必填字段的情况下)。在将该对象保存到数据库之前,显式设置这些值仍然是您的工作。
【解决方案2】:

这里的基本问题在于表单的定义。表单不适用于模型字段,而是需要表单字段。只有这样才能正确构建字段。

from django import forms

class OrderForm(forms.Form):
    delivery_time = forms.CharField(max_length=100)
    address_city = forms.CharField(max_length=40)
    address_street = forms.CharField(max_length=40)
    address_building = forms.CharField(max_length=40)

然后尝试在您的模板中输出{{ form }}

    <form action="foo" method="post">
        {% csrf_token %}   
        {{ form }}
        <input type="submit" value="submit"/>
    </div>

【讨论】:

  • 谢谢。但我为输入字段设置的 id 并不重要。这取决于名称值
  • 很高兴知道,我从答案中删除了注释。
猜你喜欢
  • 2010-09-25
  • 1970-01-01
  • 2020-01-19
  • 2014-03-04
  • 2011-09-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-18
相关资源
最近更新 更多