【问题标题】:How to make form validations in Django如何在 Django 中进行表单验证
【发布时间】:2017-11-28 16:05:03
【问题描述】:

我正在尝试进行表单验证,以便某些字段只接受某些类型的输入,例如姓名只接受字母,电话号码只接受 10 个数字。我尝试对名字进行验证,如下所示:

#forms.py

class StudentForm(forms.ModelForm):
# STEP 1 FORM
    student_id = forms.CharField(max_length=128, label="Student ID")
    first_name = forms.CharField(max_length=128, label="First Name", widget=forms.TextInput(attrs={'class': 'form-control'}))
    last_name = forms.CharField(max_length=128, label="Last Name")
    ssn = USSocialSecurityNumberField(widget=forms.TextInput(attrs={'class': 'form-control'}), label="SSN", help_text="Format: xxx-xx-xxxx")
    gender = forms.ChoiceField(widget=forms.Select(attrs={'class': 'form-control'}), label="Gender", choices=GENDER_CHOICES)
    dob = forms.DateField(widget=forms.DateInput(attrs={'class': 'form-control'}), label="Date of birth", help_text="Format: yyyy-mm-dd")
    contact_number = forms.CharField(max_length=128, label="Contact number")
    address = forms.CharField(max_length=128, label="Address")
    city = forms.CharField(max_length=128, label="City")
    state = forms.ChoiceField(choices=STATE_CHOICES, initial="NJ", label="State")
    zipcode = USZipCodeField(label="Zipcode")
    country = forms.ChoiceField(choices=countries, label="Country", initial="US")
    home_phone = forms.CharField(max_length=128, label="Home phone")
    cell_phone = forms.CharField(max_length=128, label="Cell phone")
    email = forms.EmailField(widget=forms.EmailInput(attrs={'class': 'form-control'}), max_length=254, validators=[validate_email], label="Email")
    background = forms.ChoiceField(choices=BACKGROUND_CHOICES, label="Background")
    location = forms.ChoiceField(choices=LOCATION_CHOICES, initial="south_plainfield", label="Location")
    workforce = forms.ChoiceField(choices=WORKFORCE_CHOICES, initial="--", label="Workforce")
    source = forms.ChoiceField(choices=SOURCE_CHOICES, initial="individual", label="Source")
    refer_by = forms.ChoiceField(choices=REFER_BY_CHOICES, initial="no refer", label="Refer by")
    last_status = forms.ChoiceField(choices=LAST_STATUS_CHOICES, initial="followup", label="Last status")
    newsletter = forms.BooleanField(widget=forms.CheckboxInput(), label="Newsletter", required=False)
    created_by = forms.CharField(max_length=128, label="Created by")
    date = forms.DateField(widget=forms.DateInput(attrs={'class': 'form-control'}), label="Date", help_text="Format: yyyy-mm-dd")
    notes = forms.CharField(widget=forms.Textarea(attrs={'class': 'form-control'}), required=False, label="notes", help_text="less than 1000 characters")

    def clean(self):
        cleaned_data = self.cleaned_data
        first_name = cleaned_data.get('first_name')

        if first_name.isalpha == False:
            raise forms.ValidationError('Please enter a real name.')
        elif first_name[0].isupper() == False or first_name[1:].isupper() == True:
            raise forms.ValidationError('Please capitalize properly')
        else:
            cleaned_data['first_name'] = first_name

        return cleaned_data

    class Meta:
        model = Student
        fields = ('student_id', 'first_name', 'last_name', 'ssn', 'gender', 'dob', 'contact_number', 'address', 'city', 'state', 'zipcode', 'country', 'home_phone', 'cell_phone', 'email', 'background', 'location', 'workforce', 'source', 'refer_by', 'last_status', 'newsletter', 'created_by', 'date', 'notes')

但是,当提交表单时,它完全忽略它,我的数据库浏览器显示可以接受带有数字的名称。是不是有什么我写错了,或者除了forms.py之外我还需要在其他地方更改一些代码吗?我觉得如果我能解决这个验证,其他验证应该会更容易,但如果有人能告诉我确保表单中的电话号码只有 10 个数字的正确方法,那也很好。谢谢。

【问题讨论】:

  • 如果您的目标是在数据库级别强制执行此操作,则该表单不是执行此操作的正确位置。在您的模型中为此使用验证器。此外,您应该为模型中的字段定义详细名称和 max_length。然后,您不必重新定义模型在表单中的每个字段。您可以只使用表单元类的 fields 属性。

标签: python django forms validation


【解决方案1】:

你不调用方法 isalpha:

if first_name.isalpha == False:

您创建了一个内置方法对象 isalpha,它永远不是 False。 我认为这只是一个错字,这样写:

if first_name.isalpha():
    ... # your code

使用方法 clean_phone 验证电话号码:

def clean_phone(self):
    phone = self.cleaned_data['phone']
    if not phone.isdigit():
        raise forms.ValidationError('Phone number can only contains digits')
    elif len(phone) != 10:
        raise forms.ValidationError('Length of phone number must be 10 digits')
    return phone

编辑

完全正确,你不必在forms.py文件中描述字段,你应该在models.py中做,但是一些特殊的,比如first_name必须只包含你可以在forms.py中描述的字母。

首先,在 models.py 中创建一个包含所有 db 约束(字段类型、最大长度、选项、唯一值等)的 Student 模型。考虑到 django 会自动创建 id 字段。

# models.py

class Student(models.Model):
    first_name = models.CharField(max_length=128)
    last_name = models.CharField(max_length=128)
    # Type of gender field depends on type of keys you used in GENDER_CHOICES
    # CharField for chars, IntegerField for integers
    gender = models.CharField(choices = GENDER_CHOICES, max_length=5)
    ...
    # Here you could validate your phone number length
    # But you still have to check it for valide symbols (in forms.py)
    phone = models.CharField(max_length = 10)
    # and so on for all your fields

之后,在 forms.py 中定义您的 StudetForm。您不必用约束来描述所有 Student 字段。

# forms.py

from models import Student

class StudentForm(forms.ModelForm):
    class Meta:
        model = Student
        fields = '__all__' # Django adds all fields you've described in Student
        # Then you could rename you fields labels, otherwise django will use names of model fields
        labels = {
            'first_name': 'First Name',
            'last_name': 'Last Name',
            ...
        }
        # And you also can override widgets for rendering.
        # This feature could be useful for dates, because django default widget for DateField is TextInput.
        widgets = {
            'date': forms.SelectDateWidget,
        }

    # Now you could describe all validation methods
    def clean_first_name(self):
        first_name = self.cleaned_data['first_name']
        if not first_name.isalpha():
            return ValidationError('First name must contain only letters')
        return first_name

【讨论】:

  • 它仍然没有验证。我阅读了关于不将其放入 forms.py 的评论,但我不知道这是否是正确的解决方案,因为将“form”放入模型中会引发错误。
  • 你先定义模型。伊戈尔的例子很棒。表单使用模型中定义的信息(数据类型、max_length 等)。“clean_”-“方法”只需要包含对特定列的特殊检查。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多