我是django和测试的新手,所以我不确定这个问题是否有更简单的解决方案。
我创建了一个评估应用程序,其中包含用户可以编辑,提交和更新的量规。每个量规具有预设数量的行模型,这些行模型通过外键关系连接到量规模型。用户应该能够更新多个行模型中的多个row_choice字段,并将row_choice字段发布到数据库。
为了在模板中描绘它,我决定使用ModelFormSet并遍历rubric.html中的ModelFormSet。这工作正常,但每当我尝试使用TestCase测试此布局时,我收到错误 [' ManagementForm数据丢失或已经被篡改过了']。我理解这个错误,因为测试没有使用rubric.html(其中找到ManagementForm)将视图请求传递给视图,但是应用程序在浏览器中工作,因为django模板将ManagementForm呈现为html,在视图中没有问题。
您可以使用TestCase在django中测试ModelFormSet,还是 使用LiveServerTestCase和Selenium?有没有办法让示例测试通过并仍然测试一个post请求(使用ModelFormSet时)?非常感谢任何帮助。
forms.py
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']
rubric_page视图
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 %}
models.py
来自django.db导入模型
class Student(models.Model):
firstname = models.TextField(default="")
lastname = models.TextField(default="")
lnumber = models.TextField(default="")
def __str__(self):
return self.lnumber
#TODO add models
class EdClasses(models.Model):
name = models.TextField(default='')
students = models.ManyToManyField(Student, through="Enrollment")
def __str__(self):
return self.name
class Semester(models.Model):
text = models.TextField(default='201530')
classes = models.ManyToManyField(EdClasses)
def __str__(self):
return self.text
class Rubric(models.Model):
name = models.TextField(default="Basic Rubric")
def __str__(self):
return self.name
class Row(models.Model):
CHOICES = (
(None, 'Your string for display'),
('1','Excellent'),
('2','Proficient'),
('3','Awful'),
('4','The worst ever'),
)
rubric = models.ForeignKey(Rubric)
row_choice = models.CharField(max_length=20,choices=CHOICES, default="None", blank=True)
excellenttext = models.TextField(default="")
proficienttext = models.TextField(default="")
satisfactorytext = models.TextField(default="")
unsatisfactorytext = models.TextField(default="")
def __str__(self):
return self.row_choice
class Enrollment(models.Model):
student = models.ForeignKey(Student)
edclass = models.ForeignKey(EdClasses)
grade = models.TextField(default='')
keyrubric = models.ManyToManyField(Rubric)
如何在浏览器中呈现表单:
<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>
答案 0 :(得分:1)
我过去使用的一种方法,虽然不是特别好的方法,但是使用客户端获取渲染的表单,然后使用类似BeautifulSoup的东西从中解析出所有表单数据并在必要时更新回帖。这样,您将获得所有隐藏和预填充的字段,因此您可以确保您的测试行为与用户的行为相同。