【问题标题】:Django custom formset validation with additional data from other forms使用来自其他表单的附加数据的 Django 自定义表单集验证
【发布时间】:2016-08-10 07:33:41
【问题描述】:

为了验证我的表单集,我需要使用额外的数据(表单集之外)。当它位于BaseFormSet 时,如何将该数据传递给验证函数。除了我的表单集,request.POST 还包含我需要验证的country_id。我还需要验证期间会话中的用户。下面是我的验证码:

class BaseShippingTupleFormSet(BaseFormSet):

    def clean(self):
        if any(self.errors):
            return

        for form in self.forms:
            country = TranslatedCountry.objects.get(id=country_id) #  how to get country
            shippings = ShippingTuple.objects.filter(country=country, user=user) #  how to get user
            for s in shippings:
                if value_from > s.value_from and value_from < s.value_to:
                    raise forms.ValidationError(("Please enter a value that does not overlap with already existing "
                                                 "shipping tuples for the same country ("+country.translated_name+")"))

内联注释指示缺少变量的位置(country_iduser)。任何提示或方向表示赞赏。

解决方案

在添加自定义__init__ 方法(如@Evgeny Barbashov 的回答中所建议的那样)并修复了一些其他问题后,这是可行的解决方案:

def view_with_args(request, country_id, amount):
    context = {}
    user = request.user
    country = TranslatedCountry.objects.get(id=country_id)

    CustomArgsFormSet = formset_factory(ShippingTupleForm, formset=BaseShippingTupleFormSet, extra=int(amount)-1)
    if request.method == 'POST':
        formset = CustomArgsFormSet(country, user, request.POST, request.FILES)
        if formset.is_valid():
            # save validated forms
            return redirect('success')
        else:
            context["formset"] = formset
            return render(request, 'user/dashboard/view_template.html', context)
    else:
        context["formset"] = CustomArgsFormSet(country, user)
        return render(request, 'user/dashboard/view_template.html', context)

注意

需要注意的棘手的事情是带有自定义初始化的基本表单集类的参数!参数需要作为非关键字(见上图)和request.POST 之前传递,因为它们是未命名的参数。他们还需要按正确的顺序排列,首先是自定义参数,然后是 request.POST 等。

如果顺序错误,__init__ 方法将错误地映射参数并且错误消息令人困惑。否则python不允许non-keyword arg after keyword arg

【问题讨论】:

    标签: python django django-forms formset django-validation


    【解决方案1】:

    您可以简单地为您的表单集提供一个自定义 init 方法:

    class BaseShippingTupleFormSet(BaseFormSet):
        def __init__(country_id, user, *args, **kwargs):
            self._country_id = country_id
            self._user = user
            super(BaseShippingTupleFormSet, self).__init__(*args, **kwargs)
    

    然后在 clean 方法中使用 self._country_id 和 self._user

    【讨论】:

      【解决方案2】:

      @evgeny 的代码对我不起作用,但确实如此:

      class BaseShippingTupleFormSet(BaseFormSet):
          def __init__(self, country_id, user, *args, **kwargs):
              self._country_id = country_id
              self._user = user
              super().__init__(*args, **kwargs)
      

      【讨论】:

        猜你喜欢
        • 2011-05-04
        • 1970-01-01
        • 1970-01-01
        • 2011-06-02
        • 2010-10-04
        • 1970-01-01
        • 1970-01-01
        • 2018-02-08
        • 2021-06-22
        相关资源
        最近更新 更多