发布到Django表单时,是否发布了所有字段?

时间:2018-02-16 02:45:40

标签: python django

我正在尝试为表单编写测试来模拟我只想更新一个字段的情况。这是测试:

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()进入调试器。我注意到formerrors

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数据 - 对于您没有更改的字段 - 是否与最初的相同?为什么在此测试中而不是在浏览器中触发此错误?

1 个答案:

答案 0 :(得分:1)

这与发布数据完全没有关系。问题是您的视图是一个更新,它将现有实例传递给表单,以便Django知道如何更新它。你的测试没有这样做。

(您的测试并非真正测试您的代码;您应该使用请求工厂或测试客户端调用视图,并将数据传递到那里。)