Django 中表单集的自定义验证
Custom validation for formset in Django
我不知道如何为我的表单集进行自定义验证。我试图阻止用户在同一年使用 select 超过 12 次,但是当我打印它时,cleaned_data 会作为每种形式的不同字典出现。
我想把所有的表格都归到一本字典里,看看一年出现的次数是否超过12次,或者写得更好。
我的代码:
forms.py
class SellerResultForm(forms.ModelForm):
class Meta:
model = SellerResult
fields = ('month', 'year', 'result',)
widgets = {
'month': forms.Select(attrs={'class': 'form-control',}),
'year': forms.Select(attrs={'class': 'form-control',}),
'result': forms.TextInput(attrs={'class': 'form-control',}),
}
def has_changed(self): #used for saving data from initial
changed_data = super(SellerResultForm, self).has_changed()
return bool(self.initial or changed_data)
def clean(self):
cleaned_data = super(SellerResultForm, self).clean()
print(cleaned_data)
# prints a set of dictionaries
# {'month': 4, 'year': 2017, 'id': 1, 'result': 1000}
# {'month': 5, 'year': 2017, 'id': 1, 'result': 1000}
# {'month': 6, 'year': 2017, 'id': 1, 'result': 1000}
views.py
def seller_result(request, user_id):
SellerResultFormSet = modelformset_factory(SellerResult, form=SellerResultForm, extra=1, max_num=1)
queryset = SellerResult.objects.filter(seller=user_id,).order_by('year', 'month')
formset = SellerResultFormSet(request.POST or None,
queryset=queryset,
initial=[
{'month': datetime.now().month,
'year': datetime.now().year,
'result': 1000,}])
if formset.is_valid():
instances = formset.save(commit=False)
for instance in instances:
instance.seller_id = user_id
instance.save()
context = {
'formset': formset,
}
return render(request, 'app/seller_result.html', context)
覆盖表单集的清理方法。 self.forms 将包含所有表格。
设法让它工作,下面是完整的工作代码:
forms.py
class SellerResultForm(forms.ModelForm):
class Meta:
model = SellerResult
fields = ('month', 'year', 'result',)
widgets = {
'month': forms.Select(attrs={'class': 'form-control',}),
'year': forms.Select(attrs={'class': 'form-control',}),
'result': forms.TextInput(attrs={'class': 'form-control',}),
}
def has_changed(self): #used for saving data from initial
changed_data = super(SellerResultForm, self).has_changed()
return bool(self.initial or changed_data)
#no clean method here anymore
class BaseSellerResultFormSet(BaseModelFormSet):
def clean(self):
super(BaseSellerResultFormSet, self).clean()
years = []
for form in self.forms:
year = form.cleaned_data['year']
years.append(year)
if years.count(2017) > 12:
raise forms.ValidationError('You selected more than 12 months for 2017')
然后我非常努力地让这个 ValidationError 在我的模板中呈现,错误可用 {{ formset.non_form_errors }}
而不是我最初预期的 {{ formset.errors }}
。
我不知道如何为我的表单集进行自定义验证。我试图阻止用户在同一年使用 select 超过 12 次,但是当我打印它时,cleaned_data 会作为每种形式的不同字典出现。
我想把所有的表格都归到一本字典里,看看一年出现的次数是否超过12次,或者写得更好。
我的代码:
forms.py
class SellerResultForm(forms.ModelForm):
class Meta:
model = SellerResult
fields = ('month', 'year', 'result',)
widgets = {
'month': forms.Select(attrs={'class': 'form-control',}),
'year': forms.Select(attrs={'class': 'form-control',}),
'result': forms.TextInput(attrs={'class': 'form-control',}),
}
def has_changed(self): #used for saving data from initial
changed_data = super(SellerResultForm, self).has_changed()
return bool(self.initial or changed_data)
def clean(self):
cleaned_data = super(SellerResultForm, self).clean()
print(cleaned_data)
# prints a set of dictionaries
# {'month': 4, 'year': 2017, 'id': 1, 'result': 1000}
# {'month': 5, 'year': 2017, 'id': 1, 'result': 1000}
# {'month': 6, 'year': 2017, 'id': 1, 'result': 1000}
views.py
def seller_result(request, user_id):
SellerResultFormSet = modelformset_factory(SellerResult, form=SellerResultForm, extra=1, max_num=1)
queryset = SellerResult.objects.filter(seller=user_id,).order_by('year', 'month')
formset = SellerResultFormSet(request.POST or None,
queryset=queryset,
initial=[
{'month': datetime.now().month,
'year': datetime.now().year,
'result': 1000,}])
if formset.is_valid():
instances = formset.save(commit=False)
for instance in instances:
instance.seller_id = user_id
instance.save()
context = {
'formset': formset,
}
return render(request, 'app/seller_result.html', context)
覆盖表单集的清理方法。 self.forms 将包含所有表格。
设法让它工作,下面是完整的工作代码:
forms.py
class SellerResultForm(forms.ModelForm):
class Meta:
model = SellerResult
fields = ('month', 'year', 'result',)
widgets = {
'month': forms.Select(attrs={'class': 'form-control',}),
'year': forms.Select(attrs={'class': 'form-control',}),
'result': forms.TextInput(attrs={'class': 'form-control',}),
}
def has_changed(self): #used for saving data from initial
changed_data = super(SellerResultForm, self).has_changed()
return bool(self.initial or changed_data)
#no clean method here anymore
class BaseSellerResultFormSet(BaseModelFormSet):
def clean(self):
super(BaseSellerResultFormSet, self).clean()
years = []
for form in self.forms:
year = form.cleaned_data['year']
years.append(year)
if years.count(2017) > 12:
raise forms.ValidationError('You selected more than 12 months for 2017')
然后我非常努力地让这个 ValidationError 在我的模板中呈现,错误可用 {{ formset.non_form_errors }}
而不是我最初预期的 {{ formset.errors }}
。