Django Form表单实现注册功能,无刷新返回错误信息,提高用户体验

2019-12-09 11:58:54 最后一行代码 阅读:693

分类: Django

用户注册实例:

个人比较喜欢在钩子里写验证逻辑,比较清晰

# forms.py
import re
from django import forms
from django.contrib.auth.models import User

class RegisterForm(forms.Form):
    username = forms.CharField(
        required = False,
        widget=forms.widgets.TextInput()
    )
    password = forms.CharField(
        required = False,
        widget=forms.widgets.PasswordInput()
    )
    repeat_password = forms.CharField(
        required = False,
        widget=forms.widgets.PasswordInput()
    )
    email = forms.EmailField(
        required=False,
        widget=forms.widgets.EmailInput()
    )

    def clean_username(self):
        username = self.cleaned_data['username']
        if 3 < len(username) < 10:
            raise forms.ValidationError("请输入3~10位字符")
        if User.objects.filter(username=username).exists():
            raise forms.ValidationError("该用户名已被注册")
        return username
    
    def clean_repeat_password(self):
        password = self.cleaned_data.get('password','')
        repeat_password = self.cleaned_data.get('repeat_password','')
        if not 5<len(password)<15 or re.search(r'\s|[\u4E00-\u9FA5]',password): # 不能使用中文、空格
			raise forms.ValidationError('请输入6~14个字符且不包含空格、中文')
		if password != repeat_password:
			raise forms.ValidationError('两次输入密码不一致')
		return repeat_password

    def clean_email(self):
        email = self.cleaned_data.get('email','')
        result = re.match(r'^[0-9a-zA-Z_]{0,19}@[0-9a-zA-Z]{1,13}\.[com,cn,net]{1,3}$',email)
		if not result:
			raise forms.ValidationError('请输入正确邮箱')
		elif User.objects.filter(email=email).exists():
			raise forms.ValidationError('邮箱已注册')
		return email

    
# views.py
from django.http import Http404
from django.http import JsonResponse
from django.contrib.auth.models import User
from django.contrib.auth import login, authenticate
from .forms import RegisterForm

def register(request):
    if request.method == "post":
        form = RegisterForm(request.POST)      # 初始化表单数据
        if form.is_valid():                    # 判断是否通过验证
            username = form.cleaned_data["username"]
            password = form.cleaned_data["repeat_password"]
            email = form.cleaned_data['email']
            
            user = User.objects.create_user(username, email, password)     # 创建用户
            user.save() 
            
            user = authenticate(username=username, password=password)      # 验证指定用户名、密码
            login(request, user)                                           # 登录用户
            data = {}
            data['code'] = 'SUCCESS'
            data['from'] = reverse("home")   # 假设有这么个路由(懒得写了)
        else:
            # 获取错误信息
            data = {}
            data["username_error"] = dict(form.errors).get("username","")        
            data["password_error"] = dict(form.errors).get("repeat_password","")
            data["email_error"] = dict(form.errors).get("email","")
        return JsonResponse(data)
    else:
		raise Http404('请求异常')    # 如果不是POST请求就返回404错误
            
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Document</title>
	<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
</head>
<body>
	<form action="" id="form">
		<!-- 注意:表单表单的name属性必须与后端的Form表单字段名一致 -->
		<input type="text" name="username" placeholder="用户名" class="username">
		<input type="password" name="password" placeholder="密码" class="password">
		<input type="password" name="repeat_password" placeholder="重复密码" class="repeat_password">
		<input type="text" name="email" placeholder="邮箱" class="email">
		<button class="button-login">注册/登录</button>
	</form>

	<script>
		$.ajax({
			type: "POST",
			url: "{% url 'register' %}",          // 假设有这个路由(懒得写了)
			data: $("#form").serialize(),         // 序列化表单值发送到后端
			error: function(xhr){
				console.log(xhr);
			},
			success: function(data){
				if (data['code'] == 'SUCCESS'){          // 判断是否验证成功
					location.assign(data['from']); 				
				}else{
					if (data['username']){                               
						var usernameNode = $('.username');
						usernameNode.val('');                                // 清空表单数据
						usernameNode.attr('placeholder',data['username']);   // 通过修改placeholder属性显示错误信息在表单框中
					};
					if (data['repeat_password']){
						var passwordNode = $('.password');
						var repeat_passwordNode = $('.repeat_password');
						passwordNode.val('');
						repeat_passwordNode.val('');
						passwordNode.attr('placeholder',data['repeat_password']);
						repeat_passwordNode.attr('placeholder',data['repeat_password'])
					};
					if (data['email']){
						var emailNode = $('.email');
						emailNode.val('');
						emailNode.attr('placeholder',data['email']);
					};
				};
			}
		});
	</script>
</body>
</html>

 

表单验证流程:

表单字段参数 ==》clean_xxx()  ==》 clean()

1、首先,验证表单字段自身属性抛出的错误。如"max_length"、"required"、"unique"等约束进行验证,如果验证成功则将表单字段值保存在cleaned_data字典中返回,否则抛出ValidationError错误,该错误会自动将该表单字段的错误信息保存在errors字典中,Key为表单字段名,Value为表单字段自身属性返回的错误信息。

 

2、如果上一步验证成功,则调用表单"clean_字段名()"方法验证某一个指定字段,该方法也称局部钩子。该方法最后要将验证的表单字段值作为返回值返回。如果该方法没有抛出ValidationError错误,就返回该表单字段值,否则该表单字段错误信息会添加到errors字典中,Key为表单字段名,Value为"ValidationError()"函数自定义的错误信息。可通过"表单类实例.errors['表单字段名']"获取指定表单字段错误信息。

 

3、最后,调用表单类clean()方法验证所有表单字段,该方法也称全局钩子。该方法最后要以"self.cleaned_data"作为返回值返回。如果clean()函数没有抛出ValidationError错误,则所有表单字段都验证通过,数据都会保存在cleaned_data字典中;如果抛出ValidationError错误,则将第一次抛出的错误信息保存在errors["__all__"]中,注意:在全局钩子中只会返回第一次抛出的ValidationError错误信息。

 

4、如果一直没有抛出ValidationError错误,那么"表单实例.is_valid()"将返回True。

 

表单错误获取方法:

errors.as_data()

errors.as_json()                返回JSON字符串,中文会使用Unicode编码(其中code值同上)

errors.as_ul()                   返回HTML <ul>标签字符串

errors.as_text()               返回字符串

errors.get_json_data()     返回JSON对象(其中messages值为错误信息,code值为验证失败的字段参数名)

 

 

回复:

快来抢沙发

老板赏瓶水呗
微信 微信 支付宝 支付宝