Django modelformset验证问题:如何在request.POST中使用queryset?

时间:2011-03-25 04:41:06

标签: django validation django-forms

我正在与modelformset合作,并且有点卡住了。我正在通过,使用modelformsetfactory说20个表格。这些表单在页面中构造和显示。当我在发布后返回时,我只希望验证和保存其中一些表单,而不是所有表单,具体取决于模型字段的值。

我想我可以在queryset中使用request.POST来限制我要在我的formset中要验证的表单。但这不起作用。有什么方法可以限制表格的数量吗?

对于限制我尝试的模型实例的查询集

formset = PaymentOptionFormSet(request.POST, queryset=payment_option_posted_queryset)

我收到以下错误:

IndexError at /seller/seller_profile/

list index out of range


Traceback:
File "/home/shagun/work/tinla/django/core/handlers/base.py" in get_response
  100.                     response = callback(request, *callback_args, **callback_kwargs)
File "/home/shagun/work/tinla/web/views/user_views.py" in seller_profile
  164.             formset = PaymentOptionFormSet(request.POST, queryset=payment_option_posted_queryset)           
File "/home/shagun/work/tinla/orders/forms.py" in __init__
  400.         super(BasePaymentOptionFormSet, self).__init__(*args,**kwargs)
File "/home/shagun/work/tinla/django/forms/models.py" in __init__
  423.         super(BaseModelFormSet, self).__init__(**defaults)
File "/home/shagun/work/tinla/django/forms/formsets.py" in __init__
  47.         self._construct_forms()
File "/home/shagun/work/tinla/django/forms/formsets.py" in _construct_forms
  97.             self.forms.append(self._construct_form(i))
File "/home/shagun/work/tinla/django/forms/models.py" in _construct_form
  447.             kwargs['instance'] = self.get_queryset()[i]
File "/home/shagun/work/tinla/django/db/models/query.py" in __getitem__
  172.             return self._result_cache[k]

Exception Type: IndexError at /seller/seller_profile/
Exception Value: list index out of range

我的代码如下所示:

def seller_profile(request):
    from accounts.models import PaymentOption, PaymentMode
    payment_options = PaymentOption.objects.select_related('payment_mode').filter(payment_mode__client__id=1)
    payment_option_queryset = PaymentOption.objects.filter(payment_mode__client__id='1')
    payment_option_posted_queryset = PaymentOption.objects.filter(payment_mode__client__id='1', is_active='1')

    if request.user.is_authenticated():

        PaymentOptionFormSet = modelformset_factory(PaymentOption, formset = BasePaymentOptionFormSet, extra=0, fields = ("payment_delivery_address", "bank_branch", "bank_ac_name", "bank_ac_type", "bank_ac_no", "bank_address", "bank_ifsc", "is_active"))
        user = request.user.get_profile()
        if request.method == "POST":#If the form has been submitted
            form1 = SellerProfileForm(request.POST, instance = user)
            form2 = SellerNotificationForm(request.POST, instance = user)
            formset = PaymentOptionFormSet(request.POST, queryset=PaymentOption.objects.all())

            counting = 0
            for form in formset.forms:
                counting +=1
            print "count = ",counting
            print formset.is_valid()
            if form1.is_valid() and form2.is_valid:
                form1.save()
                form2.save()
            else:
                my_acct_ctxt = getMyAccountContext(request)
                return render_to_response('seller/seller_profile.html',
                {
                    'form1': form1,
                    'form2': form2,
                    'formset': formset,
                    'error1': form1.errors,
                    'error2': form2.errors,
                    'errorformset': formset.errors,
                    'payment_options': payment_options,
                    'acc': my_acct_ctxt,
                },
                context_instance=RequestContext(request))

        else: #If the form has not been submitted 
            form1 = SellerProfileForm(instance = user)
            form2 = SellerNotificationForm(instance = user)
            formset = PaymentOptionFormSet(queryset=payment_option_queryset)
            counter = 0

        my_acct_ctxt = getMyAccountContext(request)
    return render_to_response('seller/seller_profile.html',
        {
        'form1': form1,
        'form2': form2,
        'formset': formset,
        'payment_options': payment_options,
        'acc':my_acct_ctxt,
        },
        context_instance=RequestContext(request))

1 个答案:

答案 0 :(得分:0)

如果您需要有条件地验证formset,可以覆盖formset的clean方法。下面是一个示例,说明我是如何使用内联formset在admin中完成此操作的,您可以根据自己的需要进行更改,因为Formset类非常同质。

class MyInlineFormset(forms.models.BaseInlineFormSet):
    def clean(self):
        for form in self.forms:
            try:
                if form.cleaned_data:
                    delete = form.cleaned_data.get('DELETE')
                    if not delete:
                        my_field = form.cleaned_data.get('my_field', None)
                        if my_field:
                            if my_field == 'some_value':
                              #only validate the other values
                              #if the field you're looking for
                              #has a particular value, etc
                              another_field = form.cleaned_data.get('another_field')

                              #more validation here where you can raise
                              #forms.ValidationError()

            except AttributeError:
                pass

我希望能帮到你!