zoukankan      html  css  js  c++  java
  • 基于form组件的注册 + 基于Ajax的注册

    基于form组件的注册

    urls.py

    from django.contrib import admin
    from django.urls import path
    
    from blog import views
    urlpatterns = [
        path('admin/', admin.site.urls),
    
        #注册
        path('register/', views.register),
        
    
    ]

    views.py

    #注册视图函数
    def register(request):
        form_obj = forms.RegForm()
        if request.method == "POST":
            form_obj = forms.RegForm(request.POST)
            #帮我做校验
            if form_obj.is_valid():
                #校验通过,去数据库创建一个新的用户
                # 所以经过校验的数据都保存在  form_obj.cleaned_data  (一个大 字典 中)
                # print(form_obj.cleaned_data)    #{'name': '某某某', 'pwd': '1234567', 're_pwd': '1234567'}
                del form_obj.cleaned_data["re_password"]  # 删除字典中的 re_pwd 因为数据库中没有这个属性
                models.UserInfo.objects.create_user(**form_obj.cleaned_data)
                return HttpResponse("注册成功!")
            else:
                print(form_obj.errors)
                return HttpResponse("出错啦!")
    
    
        return render(request, 'register.html',{"form_obj":form_obj})

    register.html

    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
        <meta charset="UTF-8">
        <title>注册</title>
        <meta name="viewport" content="width=device-width, initial-scale=1">
        {% load static %}
        <link rel="stylesheet" href="{% static 'bootstrap/css/bootstrap.min.css' %}">
        <style>
            .container {
                margin-top: 100px;
            }
    {#        头像图片#}
            #avatar_img {
                width: 80px;
                height: 50px;
            }
    {#        隐藏选择图片的按钮#}
            #id_avatar {
                display: none;
            }
        </style>
    </head>
    <body>
    
    
    <div class="container">
        <div class="row">
            <div class="col-md-offset-3 col-md-6">
                <form action="" method="post" class="form-horizontal" enctype="multipart/form-data">
                    {% csrf_token %}
    {#                用户名#}
                    <div class="form-group {% if form_obj.username.errors.0 %}has-error{% endif %}">
                        <label class="col-sm-2 control-label"
                               for="{{ form_obj.username.id_for_label }}">{{ form_obj.username.label }}</label>
                        <div class="col-sm-10">
                            {{ form_obj.username }}
                            <span class="help-block">{{ form_obj.username.errors.0 }}</span>
                        </div>
                    </div>
    {#                密码#}
                    <div class="form-group {% if form_obj.password.errors.0 %}has-error{% endif %}">
                        <label class="col-sm-2 control-label"
                               for="{{ form_obj.password.id_for_label }}">{{ form_obj.password.label }}</label>
                        <div class="col-sm-10">
                            {{ form_obj.password }}
                            <span class="help-block">{{ form_obj.password.errors.0 }}</span>
                        </div>
                    </div>
    {#                确认密码#}
                    <div class="form-group {% if form_obj.re_password.errors.0 %}has-error{% endif %}">
                        <label class="col-sm-2 control-label"
                               for="{{ form_obj.re_password.id_for_label }}">{{ form_obj.re_password.label }}</label>
                        <div class="col-sm-10">
                            {{ form_obj.re_password }}
                            <span class="help-block">{{ form_obj.re_password.errors.0 }}</span>
                        </div>
                    </div>
    {#                邮箱#}
                    <div class="form-group {% if form_obj.email.errors.0 %}has-error{% endif %}">
                        <label class="col-sm-2 control-label"
                               for="{{ form_obj.email.id_for_label }}">{{ form_obj.email.label }}</label>
                        <div class="col-sm-10">
                            {{ form_obj.email }}
                            <span class="help-block">{{ form_obj.email.errors.0 }}</span>
                        </div>
                    </div>
    {#                头像   因为在forms.py中没有这个input选项,只能自己写#}
                    <div class="form-group">
                        <label class="col-sm-2 control-label">头像</label>
                        <div class="col-sm-10">
    {#                        实现了点击图片相当于点击 选择头像按钮#}
                            <label for="id_avatar"><img id="avatar_img" src="/static/img/girl.png" alt=""></label>
                            <input type="file" name="avatar" id="id_avatar">
                        </div>
                    </div>
    
                    <div class="form-group">
                        <div class="col-sm-offset-2 col-sm-2">
                            <input type="submit" value="注册" class="btn btn-success">
                        </div>
                    </div>
                </form>
            </div>
        </div>
    </div>
    <script src="{% static 'jquery-3.2.1.min.js' %}"></script>
    <script src="{% static 'bootstrap/js/bootstrap.min.js' %}"></script>
    </body>
    </html>

    自己写的forms.py

    '''
    BBS 用到的form类
    '''
    
    from django import forms
    
    #定义一个注册的form类
    class RegForm(forms.Form):
        username = forms.CharField(
            max_length=16,
            label="用户名",
            widget=forms.widgets.TextInput(
                attrs={"class": "form-control"}
            ),
            error_messages={
                "max_length":"用户名最长16位",
                "require":"用户名不能为空"
            }
        )
        password = forms.CharField(
            min_length=6,
            label="密码",
            error_messages={
                "min_length": "密码至少6位",
                "require": "密码不能为空"
            },
            widget=forms.widgets.PasswordInput(
                render_value=True,
                attrs={"class":"form-control"}
            )
        )
        re_password = forms.CharField(
            min_length=6,
            label="确认密码",
            error_messages={
                "require": "确认密码不能为空"
            },
            widget=forms.widgets.PasswordInput(
                render_value=True,
                attrs={"class": "form-control"}
            )
        )
        email = forms.EmailField(
            label="邮箱",
            error_messages={
                "require": "邮箱不能为空"
            },
            widget=forms.widgets.EmailInput(
                attrs={"class": "form-control"}
            )
        )

    补充1 

    以上注册功能已经实现的差不多了,但是在 选择头像 时,选择的头像不会替换默认的图片

    改进方法如下(一个新的知识点):

    #给选择图片的input标签绑定事件
    <script>
        //找到头像的input标签,绑定change 事件
        $("#id_avatar").on("change",function () {
            //1.创建一个读文件的对象
            var filereader = new FileReader();
            //取到当前选中的头像文件
            console.log(this.files[0]);
            //读取你选中的文件
            filereader.readAsDataURL(this.files[0]);    //读文件是需要事件的(js是异步的)
            //实现等待功能
            filereader.onload = function () {
                //2.等上一步读完文件之后,把图片加载到img标签里面
                $("#avatar_img").attr("src",filereader.result);
            }
    
    
        })
    </script>

     补充2

    检验两次输入的密码是否正确

    在forms.py中添加:

    
    
    from django.core.exceptions import ValidationError
    #重写全局的钩子函数,对确认密码做校验
        def clean(self):
            password = self.cleaned_data.get('password')   #注意:一定要使用get来取值,如果直接用字典的方法取值的话,要是为空会报错的
            re_password = self.cleaned_data.get('re_password')
            if re_password and re_password != password:
                self.add_error("re_password",ValidationError("两次密码不一致"))
            else:
                return self.cleaned_data

    补充3:

    判断新创建的用户名是否已经存在:

    方法一:

        #在forms.py中添加
    
        #重写username字段的局部钩子
        def clean_username(self):
            # 判断新的用户名在数据库中是否存在
            username = self.cleaned_data.get("username")
            is_exist = models.UserInfo.objects.filter(username=username)
            if is_exist:
                # 表示用户名已经存在
                self.add_error("username",ValidationError('用户名已存在!'))

     方法二:

    在register.html中添加:

    //给input框绑定一个失去焦点的事件,失去焦点就校验用户名是否已被注册
        $("#id_username").on("blur",function () {
            //取到用户填写的值
            var username = $(this).val();
            //发请求
            $.ajax({
                url:"/check_username_exist/",
                type:"get",
                data:{"username":username},
                success:function (arg) {
                    if(arg.status){
                        //用户名已被注册
                        $("#id_username").next().text(arg.msg).parent().parent().addClass("has-error");
                    }
                }
            })
        })

    在url.py中添加:

        # 专门用来校验用户名是否已被注册的接口
        path('check_username_exist/', views.check_username_exist),

    在views.py中添加:

    #校验用户名是否已被注册
    def check_username_exist(request):
        res = {"status":0,"msg":""}
        username = request.GET.get("username")
        is_exist = models.UserInfo.objects.filter(username=username)
        if is_exist:
            #用户名已被注册
            res["status"] = 1
            res["msg"] = "用户名已被注册!"
        return JsonResponse(res)

     

     基于Ajax的注册(重点)

    其中,urls.py 和 forms.py同上

    views.py

    from blog import forms,models
    from django.shortcuts import render,redirect,HttpResponse
    
    #注册视图函数
    def register(request):
        if request.method == "POST":
            res = {"status":0,"msg":""}
            form_obj = forms.RegForm(request.POST)
            #帮我做校验
            if form_obj.is_valid():
                #校验通过,去数据库创建一个新的用户
                # 所以经过校验的数据都保存在  form_obj.cleaned_data  (一个大 字典 中)
                # print(form_obj.cleaned_data)    #{'name': '某某某', 'pwd': '1234567', 're_pwd': '1234567'}
                del form_obj.cleaned_data["re_password"]  # 删除字典中的 re_pwd 因为数据库中没有这个属性
                models.UserInfo.objects.create_user(**form_obj.cleaned_data)
                res["msg"] = "/index/"
                return JsonResponse(res)
            else:
                #print(form_obj.errors)
                #如果有错误
                res["status"] = 1
                res["msg"] = form_obj.errors
                return JsonResponse(res)
    
        form_obj = forms.RegForm()
        return render(request, 'register.html',{"form_obj":form_obj})

    register.html

    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
        <meta charset="UTF-8">
        <title>注册</title>
        <meta name="viewport" content="width=device-width, initial-scale=1">
        {% load static %}
        <link rel="stylesheet" href="{% static 'bootstrap/css/bootstrap.min.css' %}">
        <style>
            .container {
                margin-top: 100px;
            }
    {#        头像图片#}
            #avatar_img {
                width: 80px;
                height: 50px;
            }
    {#        隐藏选择图片的按钮#}
            #id_avatar {
                display: none;
            }
        </style>
    </head>
    <body>
    
    
    <div class="container">
        <div class="row">
            <div class="col-md-offset-3 col-md-6">
                <form novalidate action="" method="post" class="form-horizontal" enctype="multipart/form-data">
                    {% csrf_token %}
    {#                用户名#}
                    <div class="form-group">
                        <label class="col-sm-2 control-label"
                               for="{{ form_obj.username.id_for_label }}">{{ form_obj.username.label }}</label>
                        <div class="col-sm-10">
                            {{ form_obj.username }}
                            <span class="help-block"></span>
                        </div>
                    </div>
    {#                密码#}
                    <div class="form-group">
                        <label class="col-sm-2 control-label"
                               for="{{ form_obj.password.id_for_label }}">{{ form_obj.password.label }}</label>
                        <div class="col-sm-10">
                            {{ form_obj.password }}
                            <span class="help-block"></span>
                        </div>
                    </div>
    {#                确认密码#}
                    <div class="form-group">
                        <label class="col-sm-2 control-label"
                               for="{{ form_obj.re_password.id_for_label }}">{{ form_obj.re_password.label }}</label>
                        <div class="col-sm-10">
                            {{ form_obj.re_password }}
                            <span class="help-block"></span>
                        </div>
                    </div>
    {#                邮箱#}
                    <div class="form-group">
                        <label class="col-sm-2 control-label"
                               for="{{ form_obj.email.id_for_label }}">{{ form_obj.email.label }}</label>
                        <div class="col-sm-10">
                            {{ form_obj.email }}
                            <span class="help-block"></span>
                        </div>
                    </div>
    {#                头像#}
                    <div class="form-group">
                        <label class="col-sm-2 control-label">头像</label>
                        <div class="col-sm-10">
    {#                        实现了点击图片相当于点击 选择头像按钮#}
                            <label for="id_avatar"><img id="avatar_img" src="/static/img/girl.png" alt=""></label>
                            <input type="file" name="avatar" id="id_avatar">
                        </div>
                    </div>
    {#                注册按钮#}
                    <div class="form-group">
                        <div class="col-sm-offset-2 col-sm-2">
                            <input type="button" value="注册" class="btn btn-success" id="reg_button">
                        </div>
                    </div>
                </form>
            </div>
        </div>
    </div>
    <script src="{% static 'jquery-3.2.1.min.js' %}"></script>
    <script src="{% static 'bootstrap/js/bootstrap.min.js' %}"></script>
    <script src="{% static 'setupajax.js' %}"></script>
    <script>
        //找到头像的input标签,绑定change 事件
        $("#id_avatar").on("change",function () {
            //1.创建一个读文件的对象
            var filereader = new FileReader();
            //取到当前选中的头像文件
            console.log(this.files[0]);
            //读取你选中的文件
            filereader.readAsDataURL(this.files[0]);    //读文件是需要事件的(js是异步的)
            //实现等待功能
            filereader.onload = function () {
                //2.等上一步读完文件之后,把图片加载到img标签里面
                $("#avatar_img").attr("src",filereader.result);
            }
        });
    
        //用Ajax提交注册的数据           重点
        $("#reg_button").on("click",function () {
            //取到用户填写的注册信息,向后端发送Ajax请求
            $.ajax({
                url:"/register/",
                type:"post",
                data:{
                    username:$("#id_username").val(),
                    password:$("#id_password").val(),
                    re_password:$("#id_re_password").val(),
                    email:$("#id_email").val()
                },
                success:function (arg) {
                    if(arg.status){
                        //有错误就展示错误
                        console.log(arg.msg);
                        //将报错信息填写到页面上
                        $.each(arg.msg,function (k,v) {
    {#                        console.log("id_"+k,v[0]);#}
                            //console.log($("#id_"+k))
                            //找到对应input标签下面的 span标签 并添加内容
                            $("#id_"+k).next("span").text(v[0]);
                            $("#id_"+k).parent().parent().addClass("has-error")
                        })
                    }else{
                        //没有就跳转到指定页面
                        location.href = arg.msg;
                    }
                }
            })
        });
        //将所有的input框绑定获取焦点的事件,并将所有的错误信息清空
        $("form input").on("focus",function () {
            //this指的是当前点击的input标签
            //同时实现两个功能 1.当input框中聚焦点时,清空错误信息   2.把框的颜色 变回原来的颜色
            $(this).next().text("").parent().parent().removeClass("has-error");
        })
    </script>
    </body>
    </html>

    补充:

    但是这个还不完美,因为  头像还没有上传

    补充如下:

    views.py修改后

    #注册视图函数
    def register(request):
        if request.method == "POST":
            res = {"status":0,"msg":""}
            form_obj = forms.RegForm(request.POST)
            #帮我做校验
            if form_obj.is_valid():
                #校验通过,去数据库创建一个新的用户
                # 所以经过校验的数据都保存在  form_obj.cleaned_data  (一个大 字典 中)
                # print(form_obj.cleaned_data)    #{'name': '某某某', 'pwd': '1234567', 're_pwd': '1234567'}
                del form_obj.cleaned_data["re_password"]  # 删除字典中的 re_pwd 因为数据库中没有这个属性
                # 要自己拿头像数据  必须自己去拿 头像数据并上传到数据库
                avatar_img = request.FILES.get('avatar')
                models.UserInfo.objects.create_user(**form_obj.cleaned_data,avatar=avatar_img)
                res["msg"] = "/index/"
                return JsonResponse(res)
            else:
                # print(form_obj)
                #如果有错误
                res["status"] = 1
                res["msg"] = form_obj.errors
                return JsonResponse(res)
    
        form_obj = forms.RegForm()
        return render(request, 'register.html',{"form_obj":form_obj})

    register.html修改后

    //注意:是局部修改
    
    //用Ajax提交注册的数据
        $("#reg_button").on("click",function () {
            //取到用户填写的注册信息,向后端发送Ajax请求
    
            var formData = new FormData();
            formData.append("username",$("#id_username").val());
            formData.append("password",$("#id_password").val());
            formData.append("re_password",$("#id_re_password").val());
            formData.append("email",$("#id_email").val());
            formData.append("avatar",$("#id_avatar")[0].files[0]);
    {#        console.log(formData);#}
            $.ajax({
                url:"/register/",
                type:"post",
    {#            使用Ajax传文件必须加上下面两行数据#}
                processData:false,
                contentType:false,
    {#            使用Ajax传文件时,data必须是 FormData 类型#}
                data:formData,
                success:function (arg) {
                    if(arg.status){
                        //有错误就展示错误
    {#                    console.log(arg.msg);#}
                        //将报错信息填写到页面上
                        $.each(arg.msg,function (k,v) {
    {#                        console.log("id_"+k,v[0]);#}
                            //console.log($("#id_"+k))
                            //找到对应input标签下面的 span标签 并添加内容
    {#                        $("#id_"+k).next("span").text(v[0]);#}
    {#                        $("#id_"+k).parent().parent().addClass("has-error");#}
                            //相当于上面两步
                            $("#id_"+k).next("span").text(v[0]).parent().parent().addClass("has-error");
                        })
                    }else{
                        //没有就跳转到指定页面
                        location.href = arg.msg;
                    }
                }
            })
        });

    使用Ajax上传包含文件时的注意事项:

    1.使用Ajax传文件必须加上下面两行数据(填写在    $.ajax({})    中) 

    processData:false,

    contentType:false,

    2.使用Ajax传文件时,data必须是 FormData 类型

    如:

        //用Ajax提交注册的数据
        $("#reg_button").on("click",function () {
            //取到用户填写的注册信息,向后端发送Ajax请求
    
            var formData = new FormData();
            formData.append("username",$("#id_username").val());
            formData.append("password",$("#id_password").val());
            formData.append("re_password",$("#id_re_password").val());
            formData.append("email",$("#id_email").val());
            formData.append("avatar",$("#id_avatar")[0].files[0]);
    {#        console.log(formData);#}
            $.ajax({
                url:"/register/",
                type:"post",
    {#            使用Ajax传文件必须加上下面两行数据#}
                processData:false,
                contentType:false,
    {#            使用Ajax传文件时,data必须是 FormData 类型#}
                data:formData,
                success:function (arg) {
                    if(arg.status){
                        //有错误就展示错误
    {#                    console.log(arg.msg);#}
                        //将报错信息填写到页面上
                        $.each(arg.msg,function (k,v) {
    {#                        console.log("id_"+k,v[0]);#}
                            //console.log($("#id_"+k))
                            //找到对应input标签下面的 span标签 并添加内容
    {#                        $("#id_"+k).next("span").text(v[0]);#}
    {#                        $("#id_"+k).parent().parent().addClass("has-error");#}
                            //相当于上面两步
                            $("#id_"+k).next("span").text(v[0]).parent().parent().addClass("has-error");
                        })
                    }else{
                        //没有就跳转到指定页面
                        location.href = arg.msg;
                    }
                }
            })
        });

    小知识:

     js中each的使用:

    var obj = {"name":"小娜","age":18}
    
    $.each(obj,function(k,v){
        console.log(k,v);
    })
    
    
    >>>    name   小娜
               age      18
    
    
    #要注意格式

     js中$("...").on(" xxx  ",function(){})中xxx的介绍:

    最常见的几种使用:
    
    1. click 
        在点击后立刻执行
    
    2. focus
        聚焦后立刻执行
    
    3. blur
        失去焦点后立刻执行
    
    4. change
        改变后立刻执行
  • 相关阅读:
    JSP详细解析
    JSP详细解析
    JAVA设计模式之单例模式
    JAVA设计模式之单例模式
    SQLite – GLOB子句
    HEXO进阶打赏
    python常用模块
    猫头鹰的深夜翻译:核心JAVA并发一
    标准规范
    题解 P1951 【收费站_NOI导刊2009提高(2)】
  • 原文地址:https://www.cnblogs.com/liujie12/p/12714862.html
Copyright © 2011-2022 走看看