• bbs项02


    昨日回顾新增内容

    在models中创建
    1.ForeignKey: on_delete :有很多选项
    -models.CASCADE
    -models.SET_DEFAULT()
    2.OneToOneField就是ForeignKey+unique
    3.字段类有很多属性:
    max_length
    null=True
    default=‘sss’
    unique=True
    db_index=True
    verbose_name
    db_constraint=False 放在ForeignKey,不建立外键关联

    1.注册forms编写

    from django import forms
    from django.forms import widgets
    from django.core.exceptions import ValidationError
    from .models import UserInfo  # 相对导入和绝对导入 此处属于相对导入
    
    
    class RegisterForm(forms.Form):
        # 用户名,密码,确认密码,邮箱
        username = forms.CharField(max_length=8, min_length=3, required=True, error_messages={
            'max_length': '用户名过长',
            'min_length': '用户名过短',
            'required': '用户名必填'
        }, widget=widgets.TextInput(attrs={'class': 'form-control'}))
        password = forms.CharField(max_length=8, min_length=3, required=True, error_messages={
            'max_length': '密码过长',
            'min_length': '密码过短',
            'required': '密码必填'
        }, widget=widgets.PasswordInput(attrs={'class': 'form-control'}))
        re_password = forms.CharField(max_length=8, min_length=3, required=True, error_messages={
            'max_length': '密码过长',
            'min_length': '密码过短',
            'required': '密码必填'
        }, widget=widgets.PasswordInput(attrs={'class': 'form-control'}))
        email = forms.EmailField(widget=widgets.EmailInput(attrs={'class': 'form-control'}))
    
        # 局部钩子校验
        def clean_username(self):
            username = self.cleaned_data.get('username')
            user = UserInfo.objects.filter(username=username)  # (在django中取值)
            if user:
                # 已经存在,不合理
                return ValidationError('用户名已经存在')
            # 不存在,合理 返回校验后的数据
            else:
                return username
    
        # 全局钩子校验
        # 比较两个密码是否一致
        def clean(self):
            password = self.cleaned_data.get('password')
            re_password = self.cleaned_data.get('re_password')
            if password == re_password:
                # 密码验证正确 返回校验过后的数据
                return self.cleaned_data
            else:
                # 不合理,抛出异常
                raise ValidationError('两次密码不一致')
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48

    2.注册前端页面

    # bootstrap 搭建
    	-settings.py 中 加入static
            STATIC_URL = '/static/'
            STATICFILES_DIRS=[
                os.path.join(BASE_DIR,'static')
            ]
        -把bootstrap的静态资源copy到static文件夹下
        
    # 新建模板文件 register.html
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Titletitle>
        <link rel="stylesheet" href="/static/bootstrap/css/bootstrap.min.css">
    head>
    <body>
    <div class="container-fluid">
        <div class="row">
            <div class="col-md-6 col-md-offset-3">
                <h1 class="text-center">注册功能h1>
                <form id="id_form">
    
    
                    {% for item in form %}
                        <div class="form-group">
                            <label for="{{ item.id_for_label }}">{{ item.label }}label>
                            {{ item }}
                            <span class="pull-right text-danger">span>
                        div>
                    {% endfor %}
                    <div class="form-group">
                        <label for="id_file">头像
                            <img src="/static/img/default.png" alt="" height="80px" width="80px" style="margin-left: 10px">
                        label>
                        <input type="file" id="id_file" accept="image/*" style="display: none">
                    div>
                    <div class="form-group text-center">
                        {#                    如果input类型是submit或者button标签,放在form表单中,如果点提交,触发form的提交,如果我们写了ajax提交,会触发两次提交#}
                        <input type="button" value="注册" class="btn btn-danger" id="id_submit">
                        <span class="text-danger">span>
                    div>
    
                form>
            div>
    
        div>
    div>
    
    body>
    html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    3 头像动态显示

    DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Titletitle>
        <link rel="stylesheet" href="/static/bootstrap/css/bootstrap.min.css">
        <script src="/static/jquery-3.3.1/jquery-3.3.1.min.js">script>
    head>
    <body>
    <div class="container-fluid">
        <div class="row">
            <div class="col-md-6 col-md-offset-3">
                <h1 class="text-center">注册功能h1>
                <form id="id_form">
    
    
                    {% for item in form %}
                        <div class="form-group">
                            <label for="{{ item.id_for_label }}">{{ item.label }}label>
                            {{ item }}
                            <span class="pull-right text-danger">span>
                        div>
                    {% endfor %}
                    <div class="form-group">
                        <label for="id_file">头像
                            <img src="/static/img/default.png" alt="" height="80px" width="80px" style="margin-left: 10px" id="id_img">
                        label>
                        <input type="file" id="id_file" accept="image/*" style="display: none">
                    div>
                    <div class="form-group text-center">
                        {#                    如果input类型是submit或者button标签,放在form表单中,如果点提交,触发form的提交,如果我们写了ajax提交,会触发两次提交#}
                        <input type="button" value="注册" class="btn btn-danger" id="id_submit">
                        <span class="text-danger">span>
                    div>
    
                form>
            div>
    
        div>
    div>
    
    body>
    <script>
        $("#id_file").change(function () {
            // 把当前图片,放到img标签中
            // 把图片地址放到img标签上,标签就显示了图片
            //$("#id_img")[0].src='https://tva1.sinaimg.cn/large/00831rSTly1gd1u0jw182j30u00u043b.jpg'
    
            // 1 id_file这个标签的图片读出来,借助于文件阅读器,js提供的一个类
            var reader=new FileReader()
            // 2 拿到文件对象,赋值给一个变量
            var file =$("#id_file")[0].files[0]
            // 3 把文件读到文件阅读器中
            reader.readAsDataURL(file)
            // 4 等读完后,把文件阅读器的内容写到img标签上
            //$("#id_img")[0].src=reader.result
            reader.onload=function (){
                //$("#id_img")[0].src=reader.result
                $('#id_img').attr('src', reader.result)
            }
    
    
    
        })
    
    
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67

    4 注册功能后端

    def register(request):
        if request.method == 'GET':
            register_form = RegisterForm()
            # context: 上下文
            return render(request, 'register.html', context={'form': register_form})
        else:  # post请求的时候
            res = {'code': 100, 'msg': '注册成功'}
            # 取出用户名密码,使用form校验数据,如果校验通过,存到数据库中,如果校验不通过,返回错误信息
            register_form = RegisterForm(data=request.POST)
            if register_form.is_valid():
                # 数据字段自己的规则,局部钩子,全局钩子都校验过后,通过了
                # 1  re_password字段,不存到数据库的,剔除
                register_data = register_form.cleaned_data
                register_data.pop('re_password')
                # 2 头像:如果携带了要存,头像是文件,在request.FILES中
                my_file = request.FILES.get('my_file')
                if my_file:
                    register_data['avatar'] = my_file
                # 2 存到数据库
                UserInfo.objects.create_user(**register_data)
                # UserInfo.objects.create_user(username=register_data.get('username'),) 等同于上面,但是麻烦
                return JsonResponse(res)
            else:
                res['code'] = 101
                res['msg'] = '注册失败'
                res['errors'] = register_form.errors
                return JsonResponse(res)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    5 注册功能前端

    DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Titletitle>
        <link rel="stylesheet" href="/static/bootstrap/css/bootstrap.min.css">
        <script src="/static/jquery-3.3.1/jquery-3.3.1.min.js">script>
    head>
    <body>
    <div class="container-fluid">
        <div class="row">
            <div class="col-md-6 col-md-offset-3">
                <h1 class="text-center">注册功能h1>
                <form id="id_form" >
                    {% csrf_token %}
    
                    {% for item in form %}
                        <div class="form-group">
                            <label for="{{ item.id_for_label }}">{{ item.label }}label>
                            {{ item }}
                            <span class="pull-right text-danger">span>
                        div>
                    {% endfor %}
                    <div class="form-group">
                        <label for="id_file">头像
                            <img src="/static/img/default.png" alt="" height="80px" width="80px" style="margin-left: 10px"
                                 id="id_img">
                        label>
                        <input type="file" id="id_file" accept="image/*" style="display: none">
                    div>
                    <div class="form-group text-center">
                        {#                    如果input类型是submit或者button标签,放在form表单中,如果点提交,触发form的提交,如果我们写了ajax提交,会触发两次提交#}
                        <input type="button" value="注册" class="btn btn-danger" id="id_submit">
                        <span class="text-danger">span>
                    div>
    
                form>
            div>
    
        div>
    div>
    
    body>
    <script>
        $("#id_file").change(function () {
            // 把当前图片,放到img标签中
            // 把图片地址放到img标签上,标签就显示了图片
            //$("#id_img")[0].src='https://tva1.sinaimg.cn/large/00831rSTly1gd1u0jw182j30u00u043b.jpg'
    
            // 1 id_file这个标签的图片读出来,借助于文件阅读器,js提供的一个类
            var reader = new FileReader()
            // 2 拿到文件对象,赋值给一个变量
            var file = $("#id_file")[0].files[0]
            // 3 把文件读到文件阅读器中
            reader.readAsDataURL(file)
            // 4 等读完后,把文件阅读器的内容写到img标签上
            //$("#id_img")[0].src=reader.result
            reader.onload = function () {
                //$("#id_img")[0].src=reader.result
                $('#id_img').attr('src', reader.result)
            }
    
    
        })
    
    
        // 当点击注册按钮,发送ajax请求到后端的注册功能
        $("#id_submit").click(function () {
    
            // 上传文件,借助于formdata对象
            var formdata = new FormData()
    
            // 方式一
            /*
            formdata.append('username',$('#id_username').val())
            formdata.append('password',$('#id_username').val())
            formdata.append('re_password',$('#id_username').val())
            formdata.append('my_file',$('#id_file')[0].files[0])
            // csrftoken也要加上
            */
            // 方式二:借助于form表单批量处理
            var data = $("#id_form").serializeArray()
            console.log(data)
            // 使用for循环,把data中得数据,转存到formdata中  jquery的each循环
            $.each(data, function (i, v) {
                //console.log("索引是:",i)
                //console.log("值是:",v)
                //console.log("------")
                formdata.append(v.name, v.value)
            })
            // 文件单独再放进去
            formdata.append('my_file', $('#id_file')[0].files[0])
    
    
            // 使用ajax向后端发送请求
            // 1 三种编码格式:urlencoded,form-data,json
            // {name:lqz,age:19}--->name=lqz&age=19
            $.ajax({
                url: '/register/',
                type: 'post',
                processData: false,
                contentType: false,
                data: formdata,
                success: function (data) {
                    console.log(data)
                    if(data.code==100){
                        // 表示注册成功,跳转到登录页面
                        location.href='/login/'
                    }else {
                        // 在前端显示错误信息
                    }
                }
    
            })
    
        })
    
    
    script>
    html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120

    6 头像上传路径问题

    #咱们写项目后台静态资源中得图片,一般放在static文件夹下
    #用户上传的文件,图片等,一般放在media文件夹下
    -我们想做的是,avatar文件夹要在media文件夹下

    #django中只需要在配置文件中加一句话
    #以后再上传的文件路径是从media文件夹下开始
    MEDIA_ROOT = os.path.join(BASE_DIR, ‘media’)

    7 注册错误信息渲染

      $("#id_submit").click(function () {
    
            // 上传文件,借助于formdata对象
            var formdata = new FormData()
    
            // 方式一
            /*
            formdata.append('username',$('#id_username').val())
            formdata.append('password',$('#id_username').val())
            formdata.append('re_password',$('#id_username').val())
            formdata.append('my_file',$('#id_file')[0].files[0])
            // csrftoken也要加上
            */
            // 方式二:借助于form表单批量处理
            var data = $("#id_form").serializeArray()
            console.log(data)
            // 使用for循环,把data中得数据,转存到formdata中  jquery的each循环
            $.each(data, function (i, v) {
                //console.log("索引是:",i)
                //console.log("值是:",v)
                //console.log("------")
                formdata.append(v.name, v.value)
            })
            // 文件单独再放进去
            formdata.append('my_file', $('#id_file')[0].files[0])
    
    
            // 使用ajax向后端发送请求
            // 1 三种编码格式:urlencoded,form-data,json
            // {name:lqz,age:19}--->name=lqz&age=19
            $.ajax({
                url: '/register/',
                type: 'post',
                processData: false,
                contentType: false,
                data: formdata,
                success: function (data) {
                    console.log(data)
                    if(data.code==100){
                        // 表示注册成功,跳转到登录页面
                        location.href='/login/'
                    }else {
                        // 在前端显示错误信息
                        console.log(data)
                        // 两次密码不一致的错误渲染
                        /*
                        if(data.errors['__all__']){
                            $(".error").html(data.errors['__all__'][0])
                        }
                        */
    
                        // 其他标签的错误渲染
                        $.each(data.errors,function (k,v){
                            if (k=='__all__'){ //两次密码不一致的错误渲染
                                $(".error").html(v[0])
                            }else {
                                // 链式调用,在对应的input后的span中插入错误文字,把父div加入has-error类,整个框变红
                                $("#id_"+k).next().html(v[0]).parent().addClass('has-error')
                            }
    
                        })
    
                        // 起一个定时任务
                        setTimeout(function (){
                            // 把所有span的文字去掉,把父div中得has-error类去掉
                            $('.text-danger').html("").parent().removeClass('has-error')
                        },3000)
    
                    }
                }
    
            })
    
        })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74

    8 用户存在校验功能

    8.1 后端校验接口

    # 前端通过get把用户名传入,我们根据用户名查询数据库,如果用户名存在,返回存在,如果不存在,返回不存在
    /check_username/?username=lqz
    
    
    def check_username(request):
        # /check_username/?username=lqz
        res = {'code': 100, 'msg': '用户存在'}
        username = request.GET.get('username')
        user = UserInfo.objects.filter(username=username).first()
        if user:
            # 用户存在 
            return JsonResponse(res)
        else:
            # 用户不存在
            res['code'] = 101
            res['msg'] = '用户不存在'
            return JsonResponse(res)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    8.2 前端

    // username输入框,失去焦点,触发ajax执行
    $('#id_username').blur(function () {
    
        $.ajax({
            url: '/check_username/?username=' + $(this).val(),
            type: 'get',
            success: function (data) {
                if (data.code == 100) {
                    // 在span中插入错误信息
                    {#alert(data.msg)#}
                    $('#id_username').next().html(data.msg)
                }
            }
    
        })
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
  • 相关阅读:
    最大异或对 c++实现
    Python循环语句(一)
    热乎的过万字GameFramework讲解笔记文档
    我对需求分析的理解
    Linux修改fs.inotify.max_user_watches(“外部文件更改同步可能很慢”和“当前的 inotify(7) 监视限制太低”)
    HCIP笔记(12)
    文章列表的显示 以及创建文章 还有文章详情的基本
    C++之智能指针
    Python编程基础:字符串的正确使用
    怎么使用Consul当配置中心和动态刷新配置
  • 原文地址:https://blog.csdn.net/m0_72611192/article/details/126877335