04 用户注册

编辑本目录

基于forms组件创建表单

创建forms

from django import forms
from django.forms import widgets
class UserInfo(forms.Form):
    user=forms.CharField(max_length=32,label="用户名",widget=widgets.TextInput(attrs={"class":'form-control'}))
    pwd=forms.CharField(max_length=32,label="密码",widget=widgets.PasswordInput(attrs={"class":"form-control"}))
    re_pwd=forms.CharField(max_length=32,label="确认密码",widget=widgets.PasswordInput(attrs={"class":"form-control"}))
    email=forms.EmailField(max_length=32,label="邮箱地址",widget=widgets.EmailInput(attrs={"class":'form-control'}))
View Code

html中渲染forms组件

<form>
    {% csrf_token %}
    {% for field in form %}
        <div class="form-group">
            <label for="{{ field.id_for_label }}">{{ field.label }}:</label>{{ field }}
        </div>
    {% endfor %}
    <input type="button" class="button form-control btn-success" value="提交">
</form>
View Code

添加用户头像

添加用户图像图标

添加一个img标签,连接到static下的一个default.png文件

技巧:

  • 利用label的for属性,让点击图片等同于点击input标签
  • 将input[type='file']的标签隐藏掉,设置display属性为none
<div class="container">
    <div class="row">
        <div class="col-md-4 col-lg-offset-4">
            <form>
                {% csrf_token %}
                {% for field in form %}
                    <div class="form-group">
                        <label for="{{ field.id_for_label }}">{{ field.label }}:</label>{{ field }}
                    </div>
                {% endfor %}
                <div class="form-group">
                    <label for="avatar">头像
                        <img class="avatar_img" src="/static/app/img/default.png" style="width: 60px;height: 60px;display: inline">
                    </label>
                    <input type="file" id="avatar" style="display: none;">
                </div>
                <input type="button" class="button form-control btn-success" value="提交">
            </form>
        </div>
    </div>
</div>
View Code

用户头像预览功能

  • 获取用户选中的文件对象,通过input标签的change事件来触发
  • 获取文件对象的本地路径,一定要等图片加载完成之后再来获取文件路径
  • 修改img的src属性值
<script>
    $('#avatar').change(function () {
        //获取用户选中的文件对象
       var file_obj=$(this)[0].files[0];
        //获取当前文件对象路径
        var reader=new FileReader();//实例化一个reader
        reader.readAsDataURL(file_obj);//读取文件对象路径,读取完成后放在reader自己内部
        //待读取完后,获取url和修改imgsrc属性
        reader.onload=function () {
            var file_url=reader.result;//获取文件路径url
            //修改img标签的src属性
            $('#avatar_img').attr('src',file_url);
        };
    })
</script>
View Code

 

用ajax提交formdata数据

ajax数据提交

  • 上传的data为formdata,需要new一个
  • contentType为false
  • processData为false

方式一创建formdata的ajax代码

<script>
    //提交formdata数据
    $('input[type="button"]').click(function () {
        var formdata=new FormData();
        formdata.append("user",$("#id_user").val());
        formdata.append("pwd",$("#id_pwd").val());
        formdata.append("re_pwd",$("#id_re_user").val());
        formdata.append("email",$("#id_email").val());
        formdata.append("avatar",$("#avatar")[0].files[0]);
        formdata.append("csrfmiddlewaretoken",$("input[name='csrfmiddlewaretoken']").val());
        $.ajax({
            url:'',
            data:formdata,
            type:'post',
            contentType:false,
            processData:false,
            success:function (data) {
                console.log(data)
            },
            error:function (err) {
                console.log(err)
            }
        })
    })
</script>
View Code

方式二创建formdata

<script>
    //提交formdata数据
    $('input[type="button"]').click(function () {
        var formdata=new FormData();formdata.append("csrfmiddlewaretoken",$("input[name='csrfmiddlewaretoken']").val());#}
        var formarray= $("#form").serializeArray();
        $.each(formarray,function (index, data) {
            formdata.append(data.name,data.value);
        });
        formdata.append("avatar",$("#avatar")[0].files[0]);

        $.ajax({
            url:'',
            data:formdata,
            type:'post',
            contentType:false,
            processData:false,
            success:function (data) {
                console.log(data)
            },
            error:function (err) {
                console.log(err)
            }
        })
    })
</script>
View Code

 views代码,可通过is_ajax()验证,也可以通过request.POST验证

def register(request):
    # if request.method=='POST':
    if request.is_ajax():
        response={"user":None,"msg":None}
        form=UserInfoForm(request.POST)
        if form.is_valid():
            response['user']=form.cleaned_data.get('user');
        else:
            print(form.cleaned_data)
            print(form.errors)
            response['msg']=form.errors
        return JsonResponse(response)
View Code

 加载error提示

  • 通过jquery的each方法循环errs,每个error的index对应的和input的id有规律,其实也可以用name直接获取。查找到input标签后,通过next方法查找下一个标签
  • 在将error写入span之前,需要将所有的error信息清除掉,否则第二次提交的是第一次的error信息任然

JavaScript代码

<script>
    //提交formdata数据
    $('input[type="button"]').click(function () {
        var formdata=new FormData();
        var formarray= $("#form").serializeArray();
        $.each(formarray,function (index, data) {
            formdata.append(data.name,data.value);
        });
        formdata.append("avatar",$("#avatar")[0].files[0]);
        $.ajax({
            url:'',
            data:formdata,
            type:'post',
            contentType:false,
            processData:false,
            success:function (data) {
                if(data.msg){
                    //数据校验失败,导致注册失败
                    //动态加载错误信息
                    $(".error").html("");//先清空一次,避免上次错误信息任然存在
                    $(".form-group").removeClass('has-error');
                    $.each(data.msg,function (index,error_list) {
                        $("#id_"+index).next().html(error_list[0]);
                        $("#id_"+index).parent().addClass('has-error');//错误字段边框变红
                    })
                }else{
                    //注册成功
                }
            },
            error:function (err) {
                console.log(err)
            }
        })
    })
</script>
View Code

错误信息修改成中文提示

在form字段中,添加error_message参数

class UserInfo(forms.Form):
    user=forms.CharField(max_length=32,label="用户名",
                         widget=widgets.TextInput(attrs={"class":'form-control'}),
                         error_messages={"required":"用户名不能为空"})
    pwd=forms.CharField(max_length=32,label="密码",
                        widget=widgets.PasswordInput(attrs={"class":"form-control"}),
                         error_messages={"required":"密码不能为空"})
    re_pwd=forms.CharField(max_length=32,label="确认密码",
                           widget=widgets.PasswordInput(attrs={"class":"form-control"}),
                         error_messages={"required":"确认密码不能为空"})
    email=forms.EmailField(max_length=32,label="邮箱地址",
                           widget=widgets.EmailInput(attrs={"class":'form-control'}),
                         error_messages={"required":"邮箱不能为空"})
View Code

钩子校验数据

局部钩子检查用户名是否已经注册

class RegisterUser(forms.Form):
    user=forms.CharField(max_length=32,label="用户名",
                         widget=widgets.TextInput(attrs={"class":'form-control'}),
                         error_messages={"required":"用户名不能为空"})
    pwd=forms.CharField(max_length=32,label="密码",
                        widget=widgets.PasswordInput(attrs={"class":"form-control"}),
                         error_messages={"required":"密码不能为空"})
    re_pwd=forms.CharField(max_length=32,label="确认密码",
                           widget=widgets.PasswordInput(attrs={"class":"form-control"}),
                         error_messages={"required":"确认密码不能为空"})
    email=forms.EmailField(max_length=32,label="邮箱地址",
                           widget=widgets.EmailInput(attrs={"class":'form-control'}),
                         error_messages={"required":"邮箱不能为空"})
    #局部钩子校验用户
    def clean_user(self):
        val=self.cleaned_data.get('user')
        user=UserInfo.objects.filter(username=val).first()
        if not user:
            #返回原来的val
            return val
        else:
            raise ValidationError("该用户已注册")
View Code

全局钩子检查两次密码是否一致

class RegisterUser(forms.Form):
    user=forms.CharField(max_length=32,label="用户名",
                         widget=widgets.TextInput(attrs={"class":'form-control'}),
                         error_messages={"required":"用户名不能为空"})
    pwd=forms.CharField(max_length=32,label="密码",
                        widget=widgets.PasswordInput(attrs={"class":"form-control"}),
                         error_messages={"required":"密码不能为空"})
    re_pwd=forms.CharField(max_length=32,label="确认密码",
                           widget=widgets.PasswordInput(attrs={"class":"form-control"}),
                         error_messages={"required":"确认密码不能为空"})
    email=forms.EmailField(max_length=32,label="邮箱地址",
                           widget=widgets.EmailInput(attrs={"class":'form-control'}),
                         error_messages={"required":"邮箱不能为空"})
    #全局钩子验证两次密码
    def clean(self):
        pwd=self.cleaned_data.get('pwd')
        re_pwd=self.cleaned_data.get('re_pwd')
        if pwd and re_pwd:
            if pwd == re_pwd:
                return self.cleaned_data
            else:
                raise ValidationError('两次密码不一致')
        else:
            return self.cleaned_data
View Code

注意:全局钩子的错误放在__all__中的,所以each循环的时候判断是否是__all__即可判断是否为全局错误信息

前端JavaScript展示全局错误信息

<script>
    //提交formdata数据
    $('input[type="button"]').click(function () {
        var formdata=new FormData();
        var formarray= $("#form").serializeArray();
        $.each(formarray,function (index, data) {
            formdata.append(data.name,data.value);
        });
        formdata.append("avatar",$("#avatar")[0].files[0]);

        $.ajax({
            url:'',
            data:formdata,
            type:'post',
            contentType:false,
            processData:false,
            success:function (data) {
                if(data.msg){
                    //数据校验失败,导致注册失败
                    //动态加载错误信息
                    $(".error").html("");//先清空一次,避免上次错误信息任然存在
                    $(".form-group").removeClass('has-error');
                    $.each(data.msg,function (index,error_list) {
                        if(index == '__all__'){//
                            $("#id_re_pwd").next().text(error_list[0])
                        }
                        $("#id_"+index).next().html(error_list[0]);
                        $("#id_"+index).parent().addClass('has-error');//错误字段边框变红
                    })
                }else{
                    //注册成功
                }
            },
            error:function (err) {
                console.log(err)
            }
        })
    })
</script>
View Code

所有数据校验通过

添加用户记录

def register(request):
    # if request.method=='POST':
    if request.is_ajax():
        response={"user":None,"msg":None}
        form=RegisterUser(request.POST)
        if form.is_valid():
            response['user']=form.cleaned_data.get('user')
            user=form.cleaned_data.get('user')
            pwd=form.cleaned_data.get('pwd')
            email=form.cleaned_data.get('email')
            avatar_obj=request.FILES.get('avatar')
            if avatar_obj:
                UserInfo.objects.create_user(username=user,password=pwd,email=email,avatar=avatar_obj)
            else:
                #用户没有上传头像则不能传入avatar参数,不传和传空是不一样的
                UserInfo.objects.create_user(username=user, password=pwd, email=email)
        else:
            response['msg']=form.errors
        return JsonResponse(response)
    form=RegisterUser()
    return render(request,'register.html',{"form":form})
View Code

用户校验成功,前端跳转到登录界面

if (data.user){
     //用户校验成功,跳转到登录界面
    location.href='/login/';
}
View Code

django静态文件

django有两种静态文件:

/static/        前端需求资源

/media/       所有用户上传的文件都在该文件夹中

django配置media文件件配置,在setting文件中操作

一旦配置过media,那么FileField中上传的文件将放置在media中

 

posted @ 2018-07-26 11:44  丫丫625202  阅读(171)  评论(0编辑  收藏  举报