【问题标题】:Django modelformset validation problem: how to use queryset in request.POST?Django modelformset验证问题:如何在request.POST中使用queryset?
【发布时间】:2011-03-25 04:41:06
【问题描述】:

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

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

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

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))

【问题讨论】:

    标签: django validation django-forms


    【解决方案1】:

    如果您需要有条件地验证表单集,您可以覆盖表单集的 clean 方法。这是我如何在 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
    

    希望对你有所帮助!

    【讨论】:

    • 感谢您的回复。我找到了解决我的问题的方法。在 POST 中,我现在只验证表单集的选定表单,而不验证整个表单集。我制作了一个表单错误字典并将其传递回模板文件,而不是传递 formset.errors。这是一种解决方法,但它的工作原理。由于某种原因,清洁方法似乎不起作用。不管怎样,谢谢你的回复,学到了一些新东西。
    • 不客气。我很想看看你想出的解决方法的一个例子。干杯
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-12-09
    • 1970-01-01
    • 2022-11-23
    • 1970-01-01
    • 2017-03-04
    • 1970-01-01
    • 2011-08-02
    相关资源
    最近更新 更多