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('两次密码不一致')

2.注册前端页面

# bootstrap 搭建
	-settings.py 中 加入static
        STATIC_URL = '/static/'
        STATICFILES_DIRS=[
            os.path.join(BASE_DIR,'static')
        ]
    -把bootstrap的静态资源copy到static文件夹下
    
# 新建模板文件 register.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <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>

3 头像动态显示

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <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>

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)

5 注册功能前端

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <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>

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)

                }
            }

        })

    })

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)

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)
            }
        }

    })
})
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值