Django inlineformset未正确验证表单
我正在使用inlinemodelformset创建一系列融资表单,非常简单。但是,当我提交表单时,没有为所有字段输入任何值,表单清理方法不会引发ValidationError。在forms.py中将字段设置为required=True时,即使浏览器也不要求填充字段Django inlineformset未正确验证表单,django,django-forms,Django,Django Forms,我正在使用inlinemodelformset创建一系列融资表单,非常简单。但是,当我提交表单时,没有为所有字段输入任何值,表单清理方法不会引发ValidationError。在forms.py中将字段设置为required=True时,即使浏览器也不要求填充字段 # In models.py class Financing(models.Model): loan_name = models.CharField(max_length = 30, null
# In models.py
class Financing(models.Model):
loan_name = models.CharField(max_length = 30, null = False, blank = False)
loan_type = models.CharField(max_length = 25, choices = ( ('interest_only', 'Interest-only), ('mortgage', 'Conventional Mortgage') ), blank = False, null = False)
loan_amount = models.PositiveIntegerField(null = True, blank = True)
loan_ratio = models.DecimalField(max_digits = 4, decimal_places = 2, blank = False, null = False, default = 70) # This is how much of the total cost the loan is covering
interest_reserve = models.PositiveIntegerField(null = True, blank = True)
application_fee = models.PositiveIntegerField(null = False, blank = False)
interest_rate = models.DecimalField(max_digits = 4, decimal_places = 2)
term = models.PositiveIntegerField(null = False, blank = False)
term_unit = models.CharField(max_length = 25, null = False, blank = False, choices = ( ('years', 'Years'), ('months', 'Months'), ), default = 'years' )
compounded = models.CharField(max_length = 20, choices = ( ('annually', 'Annually'), ('semi-annually', 'semi-annually'), ('quarterly', 'Quarterly'), ('monthly', 'Monthly'), ), default = 'annually' )
start_date = models.DateField(blank = False, null = False)
discharge_date = models.DateField(blank = True, null = True)
date_created = models.DateTimeField(auto_now_add = True)
date_modified = models.DateTimeField(auto_now = True)
## Relationships
customer = models.ForeignKey(customer, related_name = 'financing_programs', on_delete = models.CASCADE) ## See model comments for this relationship comments
class FinancingForm(ModelForm):
error_css_class = 'error'
required_css_class = 'required'
class Meta:
model = Financing
fields = ['loan_name',
'loan_type',
'loan_ratio',
'interest_rate',
'term',
'application_fee',
'interest_reserve',
'start_date',
]
labels = {
'interest_rate': 'interest rate (%)',
}
def __init__(self, the_customer, *args, **kwargs):
super(FinancingForm, self).__init__(*args, **kwargs)
self.customer = the_customer
## fields
self.fields['interest_rate'].required = True
self.fields['term'].required = True
self.fields['start_date'].required = True
self.fields['application_fee'].required = True
self.fields['draw_fee'].required = True
self.fields['discharge_fee'].required = True
self.fields['interest_reserve'].required = True
self.fields['loan_name'].required = True
def clean(self, *args, **kwargs):
cd = super(FinancingForm, self).clean(*args, **kwargs)
if self.customer.estimated_start_date:
customer_start_date = self.customer.estimated_start_date
if cd.get('start_date') < customer_start_date:
self.fields['start_date'].widget.attrs.update({'class': 'error'})
msg = 'start date for financing cannot happen before the customer start date'
self.add_error('start_date', msg)
raise ValidationError(_('financing start date cannot occur before the customer start date'), code='date_error')
return cd
class BaseFinancingInlineFormSet(BaseInlineFormSet):
def __init__(self, *args, **kwargs):
super(BaseFinancingInlineFormSet, self).__init__(*args, **kwargs)
form_kwargs = self.form_kwargs
self.customer = form_kwargs.get('the_customer')
def clean(self, *args, **kwargs):
'''
Two main functionalities:
1) Ensure the total loan_ratio for all the forms do not exceed 100
2) Translate excluded_items choices to valid customer item choices
'''
if any(self.errors):
errors = self.errors
return
## 1) Total loan ratio
total_loan_ratio = 0
for form in self.forms:
if self.can_delete and self._should_delete_form(form):
continue
cd = form.cleaned_data
loan_ratio = form.cleaned_data.get('loan_ratio')
total_loan_ratio += loan_ratio
if total_loan_ratio > 100:
msg = 'This field throw the total loan ratio above the 100%'
form.add_error('loan_ratio', msg)
if total_loan_ratio > 100:
raise ValidationError(_('Total loan ratio cannot exceed 100% of the project'))
# In views.py
class CreateFinancing(View):
template_name = 'financing.html'
def dispatch(self, *args, **kwargs):
return super(CreateFinancing, self).dispatch(*args, **kwargs)
def get(self, request, *args, **kwargs):
### InlineFormSet
the_pk = self.kwargs.get('pk', None)
customer = Customer.objects.get(id = the_pk)
FinancingInlineFormset = inlineformset_factory(Customer, Financing,
form = FinancingForm,
formset = BaseFinancingInlineFormSet,
can_delete = True,
extra = extra_forms)
## instance
customer_instance_id = int(kwargs.get('customer_id', None))
customer_instance = Customer.objects.get(id = customer_instance_id)
## formset
financing_formset = FinancingInlineFormset(instance = customer_instance, prefix="financing_form", form_kwargs = {'the_customer': customer_instance })
context['formset'] = financing_formset
return render(request, self.template_name, context)
def post(self, request, *args, **kwargs):
...
financing_formset = FinancingInlineFormset(request.POST, instance = customer_instance, prefix="financing_form", form_kwargs = {'the_customer': customer_instance })
if financing_formset.is_valid():
financing_instances = financing_formset.save()
return HttpResponseRedirect(reverse('development:list_view_financing', kwargs={'proforma_id': proforma_instance_id}))
else:
errors = financing_formset.errors
non_form_errors = financing_formset.non_form_errors()
context['formset'] = financing_formset
return render(request, self.template_name, context)
models.py中的#
类别融资(models.Model):
loan_name=models.CharField(最大长度=30,null=False,blank=False)
loan_type=models.CharField(最大长度=25,选项=(‘仅限利息’、‘仅限利息’、(‘抵押’、‘常规抵押’)),blank=False,null=False)
loan_amount=models.PositiveIntegerField(null=True,blank=True)
loan_ratio=models.DecimalField(最大位数=4,小数位数=2,空格=False,null=False,默认值=70)#这是贷款覆盖的总成本的多少
利息\准备金=models.PositiveIntegerField(null=True,blank=True)
应用程序\费用=型号。阳性IntegerField(null=False,blank=False)
利率=models.DecimalField(最大位数=4,小数位数=2)
term=models.PositiveIntegerField(null=False,blank=False)
term_unit=models.CharField(最大长度=25,null=False,blank=False,选项=('years','years'),('months','months'),,默认值='years')
复合=models.CharField(最大长度=20,选项=(“每年”、“每年”)、(“半年”、“半年”)、(“季度”、“季度”)、(“每月”、“每月”),默认值=“每年”)
开始日期=models.DateField(空白=False,空=False)
出院日期=models.DateField(空白=True,空=True)
date\u created=models.DateTimeField(auto\u now\u add=True)
date\u modified=models.DateTimeField(auto\u now=True)
##关系
customer=models.ForeignKey(客户,相关的_名称='financing_programs',on_delete=models.CASCADE)##有关此关系的注释,请参阅模型注释
类别融资形式(模型形式):
error\u css\u class='error'
必需的\u css\u类='required'
类元:
模型=融资
字段=[“贷款名称”,
“贷款类型”,
"贷款比率",,
“利率”,
“期限”,
“申请费”,
"利息储备",,
“开始日期”,
]
标签={
“利率”:利率(%),
}
定义初始化(self,客户,*args,**kwargs):
超级(融资形式,自我)。\uuuuu初始值(*args,**kwargs)
self.customer=客户
##田地
self.fields['interest_rate'].required=True
self.fields['term'].required=True
self.fields['start_date'].required=True
self.fields['application_fee'].required=True
self.fields['draw_fee'].required=True
self.fields['discharge_fee'].required=True
self.fields['interest_reserve'].required=True
self.fields['loan_name'].required=True
def清洁(自身,*args,**kwargs):
cd=super(融资形式,自组织).clean(*args,**kwargs)
如果self.customer.estimated\u开始日期:
客户开始日期=self.customer.estimated开始日期
如果cd.get('开始日期')<客户开始日期:
self.fields['start_date'].widget.attrs.update({'class':'error'})
msg='融资开始日期不能早于客户开始日期'
self.add\u错误('start\u date',msg)
raise ValidationError((融资开始日期不能早于客户开始日期),code='date\U error')
返回光盘
类BaseFinancingInlineFormSet(BaseInlineFormSet):
定义初始化(self,*args,**kwargs):
super(BaseFinancingInlineFormSet,self)。\uuuuuuuuuuuu初始值(*args,**kwargs)
form_kwargs=self.form_kwargs
self.customer=form_kwargs.get('the_customer'))
def清洁(自身,*args,**kwargs):
'''
两个主要功能:
1) 确保所有表格的总贷款比率不超过100
2) 将排除的商品选项转换为有效的客户商品选项
'''
如果有(自身错误):
错误=自我错误
返回
##1)贷款总额比率
总贷款比率=0
对于self.forms中的表单:
如果self.can\u删除和self.\u应删除表单(表单):
持续
cd=表格.U数据
loan_ratio=form.cleaned_data.get('loan_ratio'))
总贷款比率+=贷款比率
如果总贷款比率>100:
msg='此字段将总贷款比率抛出到100%以上'
表格.添加错误('loan\u ratio',msg)
如果总贷款比率>100:
raise ValidationError((总贷款比率不能超过项目的100%)
#In views.py
类别(视图):
模板名称='financing.html'
def调度(自身、*args、**kwargs):
return super(CreateFinancing,self).dispatch(*args,**kwargs)
def get(自我、请求、*args、**kwargs):
###内联模板集
_pk=self.kwargs.get('pk',None)
customer=customer.objects.get(id=the_pk)
FinancingInlineFormset=inlineformset\u工厂(客户、融资、,
表格=融资表格,
formset=BaseFinancingInlineFormSet,
你能删除吗=