Python 在Django中使用ModelFormSet测试Post请求
我是django和测试新手,所以我不确定是否有更简单的解决方案 我正在创建一个评估应用程序,用户可以编辑、提交和更新该应用程序。每个量规都有预设数量的行模型,这些行模型通过外键关系连接到量规模型。用户应该能够更新多行模型中的多行选择字段,并将行选择字段发布到数据库中 为了在模板中描述这一点,我决定使用ModelFormSet并在rubric.html中迭代ModelFormSet。这工作正常,但是每当我尝试使用TestCase测试这个布局时,我都会收到错误消息 ['ManagementForm数据丢失或已被篡改']。我理解这个错误,因为测试没有使用rubric.html(ManagementForm所在的位置)将post请求传递给视图,但是应用程序在浏览器中工作,因为django模板将ManagementForm呈现为html,而html在视图中没有问题 您可以使用TestCase在django中测试ModelFormSet,还是必须使用LiveServerTestCase和Selenium?有没有办法让示例测试通过并仍然测试post请求(在使用ModelFormSet时)?非常感谢您的帮助 forms.pyPython 在Django中使用ModelFormSet测试Post请求,python,django,django-forms,django-templates,Python,Django,Django Forms,Django Templates,我是django和测试新手,所以我不确定是否有更简单的解决方案 我正在创建一个评估应用程序,用户可以编辑、提交和更新该应用程序。每个量规都有预设数量的行模型,这些行模型通过外键关系连接到量规模型。用户应该能够更新多行模型中的多行选择字段,并将行选择字段发布到数据库中 为了在模板中描述这一点,我决定使用ModelFormSet并在rubric.html中迭代ModelFormSet。这工作正常,但是每当我尝试使用TestCase测试这个布局时,我都会收到错误消息 ['ManagementForm数
class RowForm(ModelForm):
class Meta:
model = Row
fields = ['row_choice']
class RubricForm(ModelForm):
class Meta:
model = Rubric
fields = ['name']
RowFormSet = modelformset_factory(Row, fields=('row_choice',), extra=0)
失败测试的一个示例:
def test_rubric_page_can_take_post_request(self):
self.add_two_classes_to_semester_add_two_students_to_class_add_one_row()
request = HttpRequest()
request.method = "POST"
response = rubric_page(request, "EG5000", "12345678")
self.assertEqual(response.status_code, 302)
追溯:
Traceback (most recent call last):
File "C:\python33\assessmenttoolstaging\source\rubricapp\tests\tests.py", line 240, in test_rubric_page_can_take_post_request
response = rubric_page(request, "EG5000", "12345678")
File "C:\python33\assessmenttoolstaging\source\rubricapp\views.py", line 52, in rubric_page
RowFormSetWeb.clean()
File "C:\Python33\lib\site-packages\django\forms\models.py", line 645, in clean
self.validate_unique()
File "C:\Python33\lib\site-packages\django\forms\models.py", line 651, in validate_unique
forms_to_delete = self.deleted_forms
File "C:\Python33\lib\site-packages\django\forms\formsets.py", line 205, in deleted_forms
if not self.is_valid() or not self.can_delete:
File "C:\Python33\lib\site-packages\django\forms\formsets.py", line 304, in is_valid
self.errors
File "C:\Python33\lib\site-packages\django\forms\formsets.py", line 278, in errors
self.full_clean()
File "C:\Python33\lib\site-packages\django\forms\formsets.py", line 325, in full_clean
for i in range(0, self.total_form_count()):
File "C:\Python33\lib\site-packages\django\forms\formsets.py", line 115, in total_form_count
return min(self.management_form.cleaned_data[TOTAL_FORM_COUNT], self.absolute_max)
File "C:\Python33\lib\site-packages\django\forms\formsets.py", line 97, in management_form
code='missing_management_form',
django.core.exceptions.ValidationError: ['ManagementForm data is missing or has been tampered with']
标题页面视图
def rubric_page(request, edclass, studentname):
edClassSpaceAdded = re.sub('([A-Z]+)', r'\1 ', edclass)
enrollmentObj = Enrollment.objects.get(edclass__name=edClassSpaceAdded, student__lnumber=studentname)
rubricForClass = enrollmentObj.keyrubric.get()
rows = Row.objects.filter(rubric=rubricForClass)
student = Student.objects.get(lnumber=studentname)
if request.method == 'POST':
#TestCase cannot test this section of the view
RowFormSetWeb = RowFormSet(request.POST)
RowFormSetWeb.clean()
if RowFormSetWeb.is_valid():
savedFormset = RowFormSetWeb.save(commit=False)
for i in savedFormset:
i.rubric = rubricForClass
RowFormSetWeb.save()
return redirect('/'+ edclass + '/')
else:
return render(request, 'rubric.html', {'studentlnumber': student.lnumber,'studentname': student.lastname + ", " + student.firstname, 'RowFormSetWeb':RowFormSetWeb, 'rows':rows, 'edclass':edclass})
else:
RowFormSetWeb = RowFormSet(queryset=Row.objects.filter(rubric=rubricForClass))
return render(request, 'rubric.html', {'studentlnumber': student.lnumber,'studentname': student.lastname + ", " + student.firstname, 'RowFormSetWeb':RowFormSetWeb, 'rows':rows, 'edclass':edclass})
rubric.html的表单部分
<h3 id="rubricheader">TODO Pull model into view</h3>
<form method="post" action= {% url 'rubricpage' edclass=edclass studentname=studentlnumber %}>
<table border="1">
<!-- TODO fix this so that it pulls from forms.py -->
<tr>
<th></th>
<th>Excellent</th>
<th>Proficient</th>
<th>Sub-par</th>
<th>Abysmal</th>
</tr>
{{ RowFormSetWeb.management_form }}
{% for form in RowFormSetWeb %}
{{ form.id }}
<tr>
<td>{{ form.row_choice }}</td><td>{{ form.excellenttext }}</td><td>{{ form.proficienttext }}</td><td>{{ form.satisfactorytext }}<td>{{ form.unsatisfactorytext }}</td>
</tr>
{{ RowFormSetWeb.errors }}
{% endfor %}
</table>
<input name="submitbutton" type="submit" name="submit" value="Submit" id="rubricsubmit">
{% csrf_token %}
</form>
{% endblock %}
在浏览器中呈现表单的方式:
<form action="/201530/EG5000/21743148/" method="post">
<table border="1">
<!-- TODO fix this so that it pulls from forms.py -->
<tr>
<th></th>
<th>Excellent</th>
<th>Proficient</th>
<th>Sub-par</th>
<th>Abysmal</th>
</tr>
<input id="id_form-TOTAL_FORMS" name="form-TOTAL_FORMS" type="hidden" value="2"/><input id="id_form-INITIAL_FORMS" name="form-INITIAL_FORMS" type="hidden" value="2"/><input id="id_form-MIN_NUM_FORMS" name="form-MIN_NUM_FORMS" type="hidden" value="0"/><input id="id_form-MAX_NUM_FORMS" name="form-MAX_NUM_FORMS" type="hidden" value="1000"/>
<input id="id_form-0-id" name="form-0-id" type="hidden" value="3"/>
<tr>
<td><select id="id_form-0-row_choice" name="form-0-row_choice">
<option value="">Your string for display</option>
<option value="1">Excellent</option>
<option value="2">Proficient</option>
<option value="3">Awful</option>
<option value="4">The worst ever</option>
</select></td>
<td>THE BEST!</td>
<td>THE SECOND BEST!</td>
<td>THE THIRD BEST!</td>
<td>YOURE LAST</td>
</tr>
[]
<input id="id_form-1-id" name="form-1-id" type="hidden" value="4"/>
<tr>
<td><select id="id_form-1-row_choice" name="form-1-row_choice">
<option value="">Your string for display</option>
<option value="1">Excellent</option>
<option value="2">Proficient</option>
<option value="3">Awful</option>
<option value="4">The worst ever</option>
</select></td>
<td>THE GREATEST!</td>
<td>THE SECOND BEST!</td>
<td>THE THIRD BEST!</td>
<td>YOURE LAST</td>
</tr>
[]
</table>
<input id="rubricsubmit" name="submit" type="submit" value="Submit">
<input name="csrfmiddlewaretoken" type="hidden" value="0OeU2n0v8ooXHBxdUfi26xxqMIdrA50L"/>
</input></form>
杰出的
精通的
低于标准
糟糕的
要显示的字符串
杰出的
精通的
可怕的
最糟糕的
最好的!
第二好!
第三好!
你是最后一个
[]
要显示的字符串
杰出的
精通的
可怕的
最糟糕的
最伟大的!
第二好!
第三好!
你是最后一个
[]
我过去使用过的一种方法(虽然不是特别好的方法)是使用客户机获取呈现的表单,然后使用类似BeautifulSoup的方法从中解析出所有表单数据,并在必要时进行更新,然后再发回。这样,您将获得所有隐藏的和预填充的字段,因此您可以确保您的测试与用户的行为相同。我担心我可能不得不这样做。是否将表单数据作为数据关键字传递到self.client.post(url,data)中?我有点困惑,因为即使我为self.client.post提供了一个包含表单正确数据的字典,我仍然会收到可怕的管理表单错误。谢谢这是我在self.client.post上发布的内容。我将呈现的表单添加到原始帖子中。如果我遗漏了一些非常基本的东西,我道歉self.client.post(“/201530/EG5000/21743148/”,{“id_form-0-row_-choice”:“1”,“id_form-1-row_-choice”:“2”})
正如错误所说,您也需要来自管理表单的值;ie隐藏字段,如form-TOTAL\u FORMS
等。谢谢!这样才能通过考试。
<form action="/201530/EG5000/21743148/" method="post">
<table border="1">
<!-- TODO fix this so that it pulls from forms.py -->
<tr>
<th></th>
<th>Excellent</th>
<th>Proficient</th>
<th>Sub-par</th>
<th>Abysmal</th>
</tr>
<input id="id_form-TOTAL_FORMS" name="form-TOTAL_FORMS" type="hidden" value="2"/><input id="id_form-INITIAL_FORMS" name="form-INITIAL_FORMS" type="hidden" value="2"/><input id="id_form-MIN_NUM_FORMS" name="form-MIN_NUM_FORMS" type="hidden" value="0"/><input id="id_form-MAX_NUM_FORMS" name="form-MAX_NUM_FORMS" type="hidden" value="1000"/>
<input id="id_form-0-id" name="form-0-id" type="hidden" value="3"/>
<tr>
<td><select id="id_form-0-row_choice" name="form-0-row_choice">
<option value="">Your string for display</option>
<option value="1">Excellent</option>
<option value="2">Proficient</option>
<option value="3">Awful</option>
<option value="4">The worst ever</option>
</select></td>
<td>THE BEST!</td>
<td>THE SECOND BEST!</td>
<td>THE THIRD BEST!</td>
<td>YOURE LAST</td>
</tr>
[]
<input id="id_form-1-id" name="form-1-id" type="hidden" value="4"/>
<tr>
<td><select id="id_form-1-row_choice" name="form-1-row_choice">
<option value="">Your string for display</option>
<option value="1">Excellent</option>
<option value="2">Proficient</option>
<option value="3">Awful</option>
<option value="4">The worst ever</option>
</select></td>
<td>THE GREATEST!</td>
<td>THE SECOND BEST!</td>
<td>THE THIRD BEST!</td>
<td>YOURE LAST</td>
</tr>
[]
</table>
<input id="rubricsubmit" name="submit" type="submit" value="Submit">
<input name="csrfmiddlewaretoken" type="hidden" value="0OeU2n0v8ooXHBxdUfi26xxqMIdrA50L"/>
</input></form>