我正在尝试为表单编写测试来模拟我只想更新一个字段的情况。这是测试:
from django.test import TestCase
from django.forms.models import model_to_dict
class FamilyDemographicsUpdateTest(TestCase):
def test_update_phone_types_with_fields_from_family_factory(self):
# Create a family for which the employee uses an iPhone
family = FamilyFactory(employee_phone_type=Family.IPHONE)
url = reverse('dashboard:family', kwargs={'pk': family.id, 'tab': 'family-demographics'})
data = model_to_dict(instance=family, fields=FamilyDemographicsForm.base_fields)
form = FamilyDemographicsForm(data=data)
之后我使用import ipdb; ipdb.set_trace()
进入调试器。我注意到form
有errors
:
ipdb> form.errors
{'employee_email': ['This email is already taken.']}
这可以追溯到表单所基于的Family
模型。表单为ModelForm
:
class FamilyDemographicsForm(forms.ModelForm):
class Meta:
model = Family
该视图基于Django的通用UpdateView
:
class FamilyUpdate(SuccessMessageMixin, DashboardAccessMixin, UpdateView):
template_name = 'families/edit.html'
model = Family
success_message = "Family was updated successfully."
def get_form_class(self, **kwargs):
tab = self.kwargs['tab']
if tab == 'family-demographics':
return FamilyDemographicsForm
并且相应的Family
对象有clean()
方法触发此错误(在class Family(models.Model)
中):
def clean(self):
if self.employee_email:
db_user = User.objects.filter(username=self.employee_email).first()
if db_user and db_user.family and db_user.family != self:
raise ValidationError({'employee_email': 'This email is already taken.'})
if self.partner_email:
db_user = User.objects.filter(username=self.partner_email).first()
if db_user and db_user.family and db_user.family != self:
raise ValidationError({'partner_email': 'This email is already taken.'})
但是,如果我实际在浏览器中使用该表单并提交,它似乎工作正常。简而言之,当您在浏览器中提交表单时,这不等同于post
数据 - 对于您没有更改的字段 - 是否与最初的相同?为什么在此测试中而不是在浏览器中触发此错误?
答案 0 :(得分:1)
这与发布数据完全没有关系。问题是您的视图是一个更新,它将现有实例传递给表单,以便Django知道如何更新它。你的测试没有这样做。
(您的测试并非真正测试您的代码;您应该使用请求工厂或测试客户端调用视图,并将数据传递到那里。)