要验证我的formset,我需要使用其他数据(在formset之外)。当它位于BaseFormSet
时,如何将该数据传递给验证功能。除了我的formset,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_id
和user
)。任何提示或方向都表示赞赏。
在添加@Evgeny Barbashov回答建议的自定义__init__
方法并解决其他一些问题之后,这是可行的解决方案:
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)
需要注意的棘手的事情是使用自定义init的基础formset类的参数!参数需要作为非关键字传递(参见上面的视图)和request.POST
之前,因为它们是未命名的args。他们也需要按照正确的顺序,首先是自定义参数,然后是request.POST
等。
如果顺序错误,__init__
方法将错误地映射参数,并且错误消息令人困惑。否则python不允许non-keyword arg after keyword arg
。
答案 0 :(得分:1)
您只需为formset提供自定义 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
答案 1 :(得分:1)
@evgeny的代码对我不起作用,但这确实有效:
class BaseShippingTupleFormSet(BaseFormSet):
def __init__(self, country_id, user, *args, **kwargs):
self._country_id = country_id
self._user = user
super().__init__(*args, **kwargs)