我正在使用django创建一个包含孩子信息的表单集。我为此使用createview(CBV)。该窗体显示正确,它具有添加子项和删除所有正常工作的子项的功能。但是,当我单击“提交”时,将调用form_invalid
而不是form_valid
。为了知道这个问题,我打印了form.errors
,发现了以下错误
<ul class="errorlist"><li>deal_id<ul class="errorlist"><li>This field is required.</li></ul></li><li>child_name<ul class="errorlist"><li>This field is required.</li></ul></li><li>son_or_daugher<ul class="errorlist"><li>This field is required.</li></ul></li><li>child_age<ul class="errorlist"><li>This field is required.</li></ul></li><li>child_education<ul class="errorlist"><li>This field is required.</li></ul></li><li>child_occupation<ul class="errorlist"><li>This field is required.</li></ul></li></ul>
下面是我的代码
模板:-
{% extends "forms_app/base.html" %}
{% load static %}
{% block title %}{% endblock %}
{% block content %}
<h2>Profile</h2>
<hr>
<div class="col-md-4">
<form action="" method="post">{% csrf_token %}
<table class="table">
{{ childrens.management_form }}
{% for form in childrens.forms %}
{% if forloop.first %}
<thead>
<tr>
{% for field in form.visible_fields %}
<th>{{ field.label|capfirst }}</th>
{% endfor %}
</tr>
</thead>
{% endif %}
<tr class="{% cycle row1 row2 %} formset_row">
{% for field in form.visible_fields %}
<td>
{# Include the hidden fields in the form #}
{% if forloop.first %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% endif %}
{{ field.errors.as_ul }}
{{ field }}
</td>
{% endfor %}
</tr>
{% endfor %}
</table>
<input type="submit" value="Submit"/> <a href="">back to the list</a>
</form>
</div>
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="{% static 'forms_app/jquery.formset.js' %}"></script>
<script type="text/javascript">
$('.formset_row').formset({
addText: 'Add Children',
deleteText: 'Remove',
prefix: 'familymember_set'
});
</script>
{% endblock %}
查看代码
class ChildrenView(CreateView):
template_name = 'forms_app/children_form.html'
form_class = ChildrenForm
success_url = reverse_lazy('forms_app:deal-entering')
# fields = ['name','class']
def get_context_data(self, **kwargs):
data = super(ChildrenView, self).get_context_data(**kwargs)
if self.request.POST:
data['childrens'] = ChildrenFormSet(self.request.POST)
else:
print('child form initial data')
initial_list = []
try:
print('its going on')
for i in range(self.request.session['children_count'] ):
print('still going on')
for field in self.fields:
initial_list.append(self.request.session[i + field])
data['childrens'] = ChildrenFormSet(initial = initial_list)
except:
data['childrens'] = ChildrenFormSet()
# data['childrens'].extra = self.request.session['children_count']
return data
def form_valid(self, form):
if form.is_valid():
count = 0
for f in form:
for field in ['deal_id','child_name','son_or_daugher','child_age','child_education','child_occupation']:
self.request.session[count + field] = f.cleaned_data[field]
count += 1
self.request.session['children_count'] = count
for i in range(count):
for field in ['deal_id','child_name','son_or_daugher','child_age','child_education','child_occupation']:
print(self.request.session[i + field])
for field in self.fields:
self.request.session[field] = form.cleaned_data[field]
self.request.session['valid_children'] = True
return super(ChildrenView, self).form_valid(form)
def form_invalid(self,form):
if form.is_valid():
pass
print(form.errors)
print('form invalid')
return super(ChildrenView, self).form_invalid(form)
表格代码
class ChildrenForm(forms.ModelForm):
class Meta:
model = Children
fields = '__all__'
def clean(self):
print(self.cleaned_data)
ChildrenFormSet = modelformset_factory(Children,fields = '__all__',extra=1)
我已经阅读了StackOverflow上的几篇文章。我浏览了django文档,但仍然无法解决问题。请帮我。
如果您对理解有任何疑问,请发表评论,我会尽快答复。
答案 0 :(得分:1)
问题可能出在此行:
form_class = ChildrenForm
尝试删除该行或将其更改为:
form_class = ChildrenFormSet
我认为您的form_valid
正在检查“ ChildrenForm”表单。
答案 1 :(得分:1)
我认为您需要完全忽略form_valid
,因为您没有有效的ChildrenForm,因此请改用post
方法
尝试这样的事情:
def post(self, *args, **kwargs):
formset = ChildrenFormSet(self.request.POST)
if formset.is_valid():
do stuff
else :
return self.form.is_invlaid()
return redirect to your success url
答案 2 :(得分:1)
您的模板呈现ChildrenFormSet
而不是ChildrenForm
。
因此,用户在ChildrenView
验证ChildrenForm
时不可避免地使用空白集。
@HenryM提供了一种逻辑解决方案(我尚未测试过),但是它取消了使用CreateView
的含义。
我将使用FormView
来直接操作Formset:
forms.py:
class ChildrenView(FormView):
template_name = 'forms_app/children_form.html'
form_class = ChildrenFormSet
success_url = reverse_lazy('forms_app:deal-entering')
def form_valid(self, form):
"""
If the formset is valid, create the objects in the database
"""
instances = []
for sub_form in form:
obj = Children(**sub_form.cleaned_data)
instances.append(obj)
Children.objects.bulk_create(instances)
return super().form_valid(form)
def get_form_kwargs(self):
"""
Here you define the queryset that gathers the forms presented to the user.
We return none() in order to have always an empty formset and simplify the code.
"""
kwargs = super().get_form_kwargs()
kwargs["queryset"] = Children.objects.none()
return kwargs
children_form.html:
{% extends "forms_app/base.html" %}
{% load static %}
{% block title %}{% endblock %}
{% block content %}
<h2>Profile</h2>
<hr>
<div class="col-md-4">
<form action="" method="post">{% csrf_token %}
{{ form.as_table }}
<input type="submit" value="Submit"/> <a href="">back to the list</a>
</form>
</div>
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="{% static 'forms_app/jquery.formset.js' %}"></script>
<script type="text/javascript">
$('.formset_row').formset({
addText: 'Add Children',
deleteText: 'Remove',
prefix: 'familymember_set'
});
</script>
{% endblock %}