Django-禁用表单选择字段验证

2024-06-03 12:42:14 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个表单,让我首先选择一个产品类型,然后选择产品。由于我有1000多个产品,所以我使用以下内容筛选产品列表以提高性能。

我在views.py中有以下内联形式

OrderLineFormSet = inlineformset_factory(OrderHeader, OrderLine, OrderLineForm, extra = 1)

在my forms.py中,我检查是否已选择产品。如果选择了产品,我只显示具有相同产品类型的产品,以提高加载性能。如果一个产品是空的,它将加载所有的产品选项,这样我可以在选择后保存表单。

class OrderLineForm(forms.ModelForm):

def __init__(self, *args, **kwargs):
    super(OrderLineForm, self).__init__(*args, **kwargs)
    self.helper = FormHelper(self)
    self.helper.form_show_errors = True
    self.helper.error_text_inline = False
    if self.instance.product is not None:        
        self.fields['product'] = forms.ModelChoiceField(queryset=Product.objects.filter(product_type_id=self.instance.product_type_id), required=False)

结果如下

enter image description here

但是,当我更改现有表单上的产品类型(然后使用jQuery更新产品下拉列表)时,保存时会出错。我知道这是因为在下拉列表中没有选择。

enter image description here

我的问题:如何禁用此错误,以便它保存我选择的选项,而不考虑原始选项。

下面是我的视图.py

def orderline_formset(request, id=None):

OrderLineFormSet = inlineformset_factory(OrderHeader, OrderLine, OrderLineForm, extra = 1)

orderheader = None
orderid = None
orderheaderid = 0

if id:
    orderid = OrderHeader.objects.get(pk=id)

if request.POST:
    if orderid:
        form = OrderHeaderForm(request.POST, instance=orderid)
        formset = OrderLineFormSet(request.POST,instance=orderid)
    else:
        form = OrderHeaderForm(request.POST)
        formset = OrderLineFormSet(request.POST)

    if form.is_valid() and formset.is_valid():
        if orderid:
            form.save()  # update object
        else:
            orderid = form.save()  # create object
        formset.instance = orderid
        formset.save()
        messages.success(request, 'Order saved succesfully!')
        return HttpResponseRedirect('/orderline_formset/' + str(orderid.pk))

    else:  # form invalid
        messages.error(request, 'Order save error, please check mandatory fields')


else:  # request.GET
    if orderid:
        invoiceheader = "" 
        if orderid.orderheader_invoice:
            invoiceheader = " -- Invoice " + str(orderid.orderheader_invoice) 
        orderheader = "Order " + str(orderid.pk) + invoiceheader

        orderheaderid = orderid.pk
        form = OrderHeaderForm(instance=orderid)
        formset = OrderLineFormSet(instance=orderid)
    else:
        orderheader = "New Order"
        orderheaderid = 0
        form = OrderHeaderForm(instance=OrderHeader())
        formset = OrderLineFormSet(instance=OrderHeader())

return render_to_response("order-add.html", {'form' : form,'formset': formset, 
                            'orderheader': orderheader,
                            'orderheaderid': orderheaderid},
                            context_instance=RequestContext(request))

Tags: instanceselfformidif产品requestpost
3条回答

重写ModelChoiceField,例如:

class MyModelChoiceField(ModelChoiceField):

   def to_python(self, value):
        try:
            value = super(MyModelChoiceField, self).to_python(value)
        except self.queryset.model.DoesNotExist:
            key = self.to_field_name or 'pk'
            value = Product.objects.filter(**{key: value})
            if not value.exists():
               raise ValidationError(self.error_messages['invalid_choice'], code='invalid_choice')
            else:
               value= value.first()
       return value

以你的形式使用它。

self.fields['product'] = MyModelChoiceField(queryset=Product.objects.filter(product_type_id=self.instance.product_type_id), required=False)
class OrderLineForm(forms.ModelForm):

    def __init__(self, *args, **kwargs):
        super(OrderLineForm, self).__init__(*args, **kwargs)
        self.helper = FormHelper(self)
        self.helper.form_show_errors = True
        self.helper.error_text_inline = False
        self.fields['product'] = forms.ModelChoiceField(
            queryset=Product.objects.all())
        self.fields['product'].required = False

在此之后,您可以使用jquery过滤器过滤select。

你必须改变

    self.fields['product'] = forms.ModelChoiceField(queryset=Product.objects.filter(product_type_id=self.instance.product_type_id), required=False)

    self.fields['product'] = forms.ModelChoiceField(queryset=Product.objects.all(), required=False)

但是你已经知道了,并且出于性能的原因不想要它,所以你的另一个解决方案是将它改为

self.fields['product'] = ModelChoiceField(queryset=Product.objects.all(),  widget=forms.HiddenInput, required=False)

然后在模板中手动构造<select>标记并使用JS handleonchange事件,使其更新产品字段

相关问题 更多 >