5

我有一个相对标准的RegistrationForm,如下所示:

class RegisterForm(forms.Form):
    username = forms.CharField(widget=forms.TextInput(attrs={'placeholder': 'username'}), initial='')
    email = forms.EmailField(widget=forms.TextInput(attrs={'placeholder': 'email'}), initial='')
    password = forms.CharField(widget=forms.PasswordInput(attrs={'placeholder': 'password'}), initial='')
    password_repeat = forms.CharField(widget=forms.PasswordInput(attrs={'placeholder': 'retype password'}), initial='')

当用户忘记填写一个或多个字段时,如何创建一个返回错误的干净方法?(即“您忘记填写电子邮件字段”)

我在 clean() 方法中尝试了以下两个选项(我将使用 password 和 password_repeat 字段作为示例):

password = self.cleaned_data['password']
password_repeat = self.cleaned_data['password_repeat']
# initial values are set to '' for all fields, see above.
if password == '':
    raise forms.ValidationError("You forgot to type in a password.")
elif password_repeat == '':
        raise forms.ValidationError("You forgot to retype your password.")

第一个选项返回:

/homepage/ 处的 KeyError

'密码'


try:
    password = self.cleaned_data['password']
    password_repeat = self.cleaned_data['password_repeat']
except KeyError(password):
    raise forms.ValidationError("You forgot to fill in the password field.")

第二个选项返回:

/homepage/ 处的 UnboundLocalError

赋值前引用的局部变量“密码”


如果您可以提供允许检查剩余字段的解决方案(以便我可以返回绑定到用户成功提交的数据的表单),则可以加分。

4

3 回答 3

5

您可以使用required可用于所有字段类型的属性,它会自动执行此类验证。所以你的代码看起来像:

class RegisterForm(forms.Form):
    username = forms.CharField(
        widget = forms.TextInput(attrs = {'placeholder': 'username'}),
        required = True)
    email = forms.EmailField(
        widget = forms.TextInput(attrs = {'placeholder': 'email'}),
        required = True)
    password = forms.CharField(
        widget = forms.PasswordInput(attrs = {'placeholder': 'password'}),
        required = True)
    password_repeat = forms.CharField(
        widget = forms.PasswordInput(attrs = {'placeholder': 'retype password'}),
        required = True)

注意:我认为您也可以省略这些initial = ''参数,如上所示。

我实际上不确定您为什么会收到您在问题中提到的错误,也许您可​​以从您的views.py? 这可能是因为您需要在您实现的任何方法cleaned_data结束时返回。clean

我也只想说你使用的clean方法不太对。如果您参考有关表单和字段验证的文档的此页面,您会看到要验证单个字段,您使用特定的clean_<fieldname>方法,例如clean_password_repeat。当验证同时涉及多个字段时,使用该clean方法是合适的,您可能喜欢使用的一个示例是检查两个密码字段的输入是否匹配。

class RegisterForm(forms.Form):
    # field definitions (above)

    def clean(self):
        password = self.cleaned_data['password']
        password_repeat = self.cleaned_data['password_repeat']
        if password != password_repeat:
            raise forms.ValidationError(u"Passwords do not match.")
        return cleaned_data

注意:代码未经测试。

我希望这可以帮到你!

于 2012-11-21T23:42:09.070 回答
1

从 django 1.2 开始,它能够在模型上编写验证代码。我总是在模型端编写业务规则:

这是你的模型:

from django.db import models
class Issue(models.Model):
    ....

    def clean(self): 
        rules.Issue_clean(self)

#I write business rules into another file ...
def Incidencia_clean( instance ): 
    import datetime as dt

    errors = {}

    #some business rules:     
    if not instance.dia_incidencia: 
        errors.setdefault('b1',[]).append(u'Falten...ranja')

    if not  instance.franja_incidencia: 
        errors.setdefault('b2',[]).append(u'Falten..nja')

    if instance.dia_incidencia < ( dt.date.today() + 
                                   dt.timedelta( days = -7) ): 
        errors.setdefault('b3',[]).append(u'''No es ... setmana)''')

    if instance.getDate() > datetime.now(): 
        errors.setdefault('b4',[]).append(u'''Encara ...itzat.''') 

    if len( errors ) > 0: 
        raise ValidationError(errors) 

在模板中:

{% if form.non_field_errors %}
      {% for error in form.non_field_errors %}
        {{error}}
      {% endfor %}
{% endif %}  

我更喜欢在模型中编写一次业务规则,而不是在每个表单中重复规则。

于 2012-11-21T21:47:58.570 回答
0

这是一个片段,它遍历字典中的键,如果其中任何一个映射到空字符串或任何其他类似 False 的值,则会引发异常。异常告诉您字典中的哪个键缺少条目。

for key in self.cleaned_data:
    if not self.cleaned_data[key]:
        raise forms.ValidationError("You didn't fill in the {} form".format(key))

如果您只想测试空字符串(而不是False, 0,[]等),请更改if not self.cleaned_data[key]:if self.cleaned_data[key] == '':.

于 2012-11-21T21:49:32.523 回答