我无法使用formset运行Unit Test.
我尝试做一个测试:
class NewClientTestCase(TestCase): def setUp(self): self.c = Client() def test_0_create_individual_with_same_adress(self): post_data = { 'ctype': User.CONTACT_INDIVIDUAL, 'username': 'dupond.f', 'email': 'new@gmail.com', 'password': 'pwd', 'password2': 'pwd', 'civility': User.CIVILITY_MISTER, 'first_name': 'François', 'last_name': 'DUPOND', 'phone': '+33 1 34 12 52 30', 'gsm': '+33 6 34 12 52 30', 'fax': '+33 1 34 12 52 30', 'form-0-address1': '33 avenue Gambetta', 'form-0-address2': 'apt 50', 'form-0-zip_code': '75020', 'form-0-city': 'Paris', 'form-0-country': 'FRA', 'same_for_billing': True, } response = self.c.post(reverse('client:full_account'), post_data, follow=True) self.assertRedirects(response, '%s?created=1' % reverse('client:dashboard'))
我有这个错误:
ValidationError:[u'ManagementForm数据丢失或被篡改']
我的看法 :
def full_account(request, url_redirect=''): from forms import NewUserFullForm, AddressForm, BaseArticleFormSet fields_required = [] fields_notrequired = [] AddressFormSet = formset_factory(AddressForm, extra=2, formset=BaseArticleFormSet) if request.method == 'POST': form = NewUserFullForm(request.POST) objforms = AddressFormSet(request.POST) if objforms.is_valid() and form.is_valid(): user = form.save() address = objforms.forms[0].save() if url_redirect=='': url_redirect = '%s?created=1' % reverse('client:dashboard') logon(request, form.instance) return HttpResponseRedirect(url_redirect) else: form = NewUserFullForm() objforms = AddressFormSet() return direct_to_template(request, 'clients/full_account.html', { 'form':form, 'formset': objforms, 'tld_fr':False, })
和我的表格文件:
class BaseArticleFormSet(BaseFormSet): def clean(self): msg_err = _('Ce champ est obligatoire.') non_errors = True if 'same_for_billing' in self.data and self.data['same_for_billing'] == 'on': same_for_billing = True else: same_for_billing = False for i in [0, 1]: form = self.forms[i] for field in form.fields: name_field = 'form-%d-%s' % (i, field ) value_field = self.data[name_field].strip() if i == 0 and self.forms[0].fields[field].required and value_field =='': form.errors[field] = msg_err non_errors = False elif i == 1 and not same_for_billing and self.forms[1].fields[field].required and value_field =='': form.errors[field] = msg_err non_errors = False return non_errors class AddressForm(forms.ModelForm): class Meta: model = Address address1 = forms.CharField() address2 = forms.CharField(required=False) zip_code = forms.CharField() city = forms.CharField() country = forms.ChoiceField(choices=CountryField.COUNTRIES, initial='FRA')
小智.. 22
特别是,我发现ManagmentForm验证器正在寻找以下要发布的项目:
form_data = { 'form-TOTAL_FORMS': 1, 'form-INITIAL_FORMS': 0 }
Bartek.. 14
每个Django formset都带有一个需要包含在帖子中的管理表单.在官方的文档解释得很好.要在单元测试中使用它,您需要自己编写.(我提供的链接显示了一个示例),或调用formset.management_form
输出数据.
特别是,我发现ManagmentForm验证器正在寻找以下要发布的项目:
form_data = { 'form-TOTAL_FORMS': 1, 'form-INITIAL_FORMS': 0 }
每个Django formset都带有一个需要包含在帖子中的管理表单.在官方的文档解释得很好.要在单元测试中使用它,您需要自己编写.(我提供的链接显示了一个示例),或调用formset.management_form
输出数据.
实际上,通过检查响应的上下文很容易重现表单集中的内容。
考虑以下代码(self.client
作为常规测试客户端):
url = "some_url" response = self.client.get(url) self.assertEqual(response.status_code, 200) # data will receive all the forms field names # key will be the field name (as "formx-fieldname"), value will be the string representation. data = {} # global information, some additional fields may go there data['csrf_token'] = response.context['csrf_token'] # management form information, needed because of the formset management_form = response.context['form'].management_form for i in 'TOTAL_FORMS', 'INITIAL_FORMS', 'MIN_NUM_FORMS', 'MAX_NUM_FORMS': data['%s-%s' % (management_form.prefix, i)] = management_form[i].value() for i in range(response.context['form'].total_form_count()): # get form index 'i' current_form = response.context['form'].forms[i] # retrieve all the fields for field_name in current_form.fields: value = current_form[field_name].value() data['%s-%s' % (current_form.prefix, field_name)] = value if value is not None else '' # flush out to stdout print '#' * 30 for i in sorted(data.keys()): print i, '\t:', data[i] # post the request without any change response = self.client.post(url, data)
如果您data
在调用之前进行了修改self.client.post
,则可能会使数据库发生突变。结果,后续的调用self.client.get
可能不会产生相同的数据,尤其是对于管理表单和表单在表单集中的顺序而言(因为根据基础查询集,它们的顺序可以不同)。这意味着
如果修改data[form-3-somefield]
和调用self.client.get
,这同一领域可能出现在说data[form-8-somefield]
,
如果您data
在之前进行修改self.client.post
,则无法self.client.post
使用进行相同的data
调用:您必须调用self.client.get
并data
再次进行重构。