关于将一个对象与另一个对象进行比较的Django形式验证器

时间:2016-04-18 17:22:45

标签: django django-models django-forms django-templates django-views

我正在创建一个用户在注册和登录后填写的“保密协议”表单。我正在使用AllAuth的自定义注册表单并预先填充表单的部分内容。我将第一个和最后一个名字预填充到表单的顶部,如下面的第一个屏幕截图所示,但作为我正在设置的数字签名的一部分;我需要验证键入的签名字段是否匹配第二个屏幕截图中连接在一起的first_namelast_name的名称。我知道我需要设置一个基于Django Form & Field Validations的验证器,我已经尝试了几件事,但是我无法理解它。将这些放在一起的任何帮助都将是巨大的......谢谢。 enter image description here

enter image description here 我的模特

class Profile(models.Model):
    user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="profile", verbose_name="user")
    ...

class NonDisclosure(Timestamp):
    profile = models.ForeignKey(Profile, on_delete=models.CASCADE, related_name="nda", verbose_name="profile")
    user_signature = models.CharField(max_length=250, verbose_name='Signature')
    user_street = models.CharField(max_length=250, verbose_name='Street Address')
    user_city = models.CharField(max_length=250, verbose_name='City')
    user_state = models.CharField(max_length=2, verbose_name='State Initials')
    user_zip = models.IntegerField(verbose_name='Zip Code')
    phone = models.CharField(max_length=25, verbose_name='Phone Number')
    cash_on_hand = models.CharField(max_length=250, verbose_name='Cash on Hand')
    value_of_securities = models.CharField(max_length=250, verbose_name='Value of Securities')
    equity_in_real_estate = models.CharField(max_length=250, verbose_name='Equity on Real Estate')
    other = models.CharField(max_length=250, verbose_name='Other Assets')

    @property
    def username(self):
        return self.profile.username

    @property
    def first_name(self):
        return self.profile.first_name

    @property
    def last_name(self):
        return self.profile.last_name

    @property
    def email(self):
        return self.profile.email

    class Meta:
        verbose_name = 'Non Disclosure Agreement'
        verbose_name_plural = 'Non Disclosure Agreements'

    def __str__(self):
        return "%s" % self.profile

    def get_absolute_url(self):
        return reverse('nda_detail', args=[str(self.id)])

我的观点:

class NonDisclosureForm(BaseModelForm):
    cash_on_hand = forms.CharField(required=False)
    value_of_securities = forms.CharField(required=False)
    equity_in_real_estate = forms.CharField(required=False)
    other = forms.CharField(required=False)

    class Meta:
        model = NonDisclosure
        fields = ['user_signature', 'user_street', 'user_city', 'user_state', 'user_zip', 'phone', 'cash_on_hand', 'value_of_securities', 'equity_in_real_estate', 'other']

class NdaCreate(CreateView):
    form_class = NonDisclosureForm
    template_name = 'nda/nda_form.html'

    def form_valid(self, form):
        form.instance.profile = Profile.objects.get(user=self.request.user)
        form.instance.created_by = self.request.user
        return super(NdaCreate, self).form_valid(form)

1 个答案:

答案 0 :(得分:1)

首先,您应该将ModelForm作为子类,而不是BaseModelForm。为user_signature字段写一个clean_<fieldname>方法,并确保该值符合预期。您可以访问self.instance.created_by进行检查。

class NonDisclosureForm(ModelForm):
    ...

    class Meta:
        model = NonDisclosure
        fields = ['user_signature', ...]

    def clean_user_signature(self):
        user_signature = self.cleaned_data['user_signature']
        expected_name = '%s %s' % (self.instance.created_by.first_name, self.instance.created_by.last_name)
        if user_signature != expected_name:
            raise forms.ValidationError('Signature does not match')
        return user_signature

然后,您需要更新视图,以便设置instance.created_by。您可以通过覆盖get_form_kwargs来完成此操作。

class NdaCreate(CreateView):

    def get_form_kwargs(self):
        kwargs = super(NdaCreate, self).get_form_kwargs()
        kwargs['instance'] = NonDisclosure(created_by=self.request.user)
        return kwargs