• 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=" 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中

  • 相关阅读:
    [团队项目]典型用户
    0415 操作系统_实验二、作业调度模拟程序
    0415 结对2.0评价
    复利计算- 结对2.0--复利计算WEB升级版
    0408汉堡
    复利计算- 结对1.0
    0405《构建之法》第四章读后感
    复利计算器4.0 【java版】
    复利计算器的单元测试结果
    操作系统 实验一、命令解释程序的编写实验
  • 原文地址:https://www.cnblogs.com/yaya625202/p/9370888.html
Copyright © 2020-2023  润新知