Django ChoiceField或TypedChoiceField以及无效的id选择

时间:2011-10-23 09:33:13

标签: django choicefield

我正在Django中编写一个简单的表单,其中包含一个ChoiceField,允许用户从类别列表中进行选择。我肯定想传递要处理的category_id。这是我的代码:

models.py:

class Category(models.Model):
      category = models.CharField(max_length=128)

      def __unicode__(self):
           return self.category


class Product(models.Model):
      code = models.CharField(max_length=75)
      name = models.CharField(max_length=128)
      price = models.DecimalField(max_digits=7, decimal_places=2)
      category = models.ForeignKey(Category)

      def __unicode__(self):
           return self.name

forms.py

class AddProductForm(forms.Form):
    category = forms.ChoiceField(label=_('Category'))
    product = forms.CharField(label=_('Product'), widget=forms.TextInput())
    code = forms.CharField(label=_('Code'), widget=forms.TextInput())
    price = forms.DecimalField(label=_('Price'))

现在在views.py中我填写了选项:

def add_product_form(request):
    form = AddProductForm()

    form.fields['category'].choices =[(c.id, c.category) for c in Category.objects.all()] 

    return render_to_response('product-form.html', {'form':form})

现在一切似乎都没问题,除非我提交表格。它抱怨类别的ID。它说: 选择有效的选择。 1不是可用选项之一

这就是我处理表单的方式:

def add_product(request):
   if request.method == 'POST':
       form = AddProductForm(request.POST)

       if form.is_valid():
           category = request.cleaned_data['category']
           product = form.cleaned_data['product']
           code = form.cleaned_data['code']
           price = form.cleaned_data['price']

           product = Product(code=code, name=product, price=price, category_id=category)

           product.save()

           return HttpResponseRedirect('/ms-admin/')
       else:
           form = AddProductForm() # more is required here to fill the choices again

       return render_to_response('product-form.html', {'form':form})

我尝试使用TypedChoiceField,但获得了相同的无效数据。我知道它与string和int以及unicode之间的转换有关。你能解释一下吗?

2 个答案:

答案 0 :(得分:2)

出于某种原因,您已经分离了呈现表单的视图(包括添加选项)和处理提交的视图。您不会在提交时添加选项,因此这些值当然不会有效。

你应该完全摆脱add_product_form视图。您可以将form.fields['category'].choices...位移到add_product视图中,但更好的解决方案是使用专门用于从模型或查询集中进行选择的表单字段 - 即ModelChoiceField

只需使用:

category = forms.ModelChoiceField(model=Category)

在表单定义中。

答案 1 :(得分:0)

谢谢丹尼尔。我不久前开始学习Django,我有这种倾向来添加一个视图来显示一个表单,这是没有必要的。所以是的,我摆脱了 add_product_form ,完全依赖于 add_product 。至于Category选择字段,现在在forms.py中编码如下:

forms.py:

from django import forms
from django.utils.translation import ugettext_lazy as _

from myapp.models import Category

class AddProductForm(forms.Form):
    category = forms.ModelChoiceField(label=_('Category'), queryset=Category.objects.all())
    product = forms.CharField(label=_('Product'), widget=forms.TextInput())
    code = forms.CharField(label=_('Code'), widget=forms.TextInput())
    price = forms.DecimalField(label=_('Price'))

views.py:

def add_product(request):
   if request.method == 'POST':
      form = AddProductForm(request.POST)

      if form.is_valid():
         category = request.POST['category']
         product = form.cleaned_data['product']
         code = form.cleaned_data['code']
         price = form.cleaned_data['price']

         product = Product(code=code, name=product, price=price, category_id=category)

         product.save()

         # redirect to 'ms-admin/category_id' (the category to which belongs the newly added product
         return HttpResponseRedirect('/ms-admin/'+category)
     else:
         form = AddProductForm()

     return render_to_response('product-form.html', {'form':form})

我希望这有助于django的新人。请随意提及改进上述代码的任何方法......