Django ModelForm中使用鉤子函式校驗資料

蕭碧宰至發表於2020-12-29

ModelForm中使用鉤子函式校驗資料

class RegisterForm(forms.ModelForm):
    password = forms.CharField(label='密碼', widget=forms.PasswordInput(), min_length=6, max_length=32, error_messages={'min_length': '密碼長度不能小於6個字元', 'max_length': '密碼長度不能大於32個字元'})
    re_password = forms.CharField(label='確認密碼', widget=forms.PasswordInput(), min_length=6, max_length=32, error_messages={'min_length': '密碼長度不能小於6個字元', 'max_length': '密碼長度不能大於32個字元'})
    phone = forms.CharField(label='手機號', validators=[RegexValidator(r'^(1[3|4|5|6|7|8|9])\d{9}$', '手機號格式錯誤')])
    code = forms.CharField(label='驗證碼', widget=forms.TextInput())

    class Meta:
        model = models.User
        fields = ['username', 'password', 're_password', 'email', 'phone', 'code']

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        for field in self.fields.values():
            field.widget.attrs['class'] = 'form-control'
            field.widget.attrs['placeholder'] = '請輸入{}'.format(field.label)
# 驗證使用者名稱
    def clean_username(self):
        # 校驗資料前,都需要獲取到被校驗的資料
        username = self.cleaned_data['username']

        # 開始校驗:判斷資料庫中是否已存在使用者名稱
        exists = models.User.objects.filter(username=username).exists()
        if exists:
            raise ValidationError('使用者名稱已存在')

        return username

    # 驗證郵箱
    def clean_email(self):
        email = self.cleaned_data['email']
        exists = models.User.objects.filter(email=email).exists()
        if exists:
            raise ValidationError('郵箱已存在')
        return email

    # 加密密碼
    def clean_password(self):
        pwd = self.cleaned_data['password']
        return md5(pwd)

    # 驗證確認密碼
    def clean_re_password(self):
        pwd = self.cleaned_data['password']
        re_pwd = md5(self.cleaned_data['re_password'])
        if pwd != re_pwd:
            raise ValidationError('兩次密碼不一致')
        return re_pwd

    # 驗證手機號
    def clean_phone(self):
        phone = self.cleaned_data['phone']
        exists = models.User.objects.filter(phone=phone).exists()
        if exists:
            raise ValidationError('手機號已被註冊')

        return phone

    # 驗證code
    def clean_code(self):
        code = self.cleaned_data['code']
        phone = self.cleaned_data['phone']

        # 連線redis
        conn = get_redis_connection()
        # 獲取redis中儲存的資料{'phone': 'code'}
        redis_code = conn.get(phone)

        if not redis_code:
            raise ValidationError('驗證碼失效或未傳送,請重新傳送')

        redis_str_code = redis_code.decode('utf-8')
        # 判斷輸入的code是否等於redis儲存的code
        if code.strip() != redis_str_code:
            raise ValidationError('驗證碼錯誤,請重新輸入')

        return code

相關文章