django框架之BBS项目之注册

内容回顾
    1. BBS项目登录
        1. 登录用form组件和auth模块
            1. form组件做校验很方便
            2. auth模块
                - authenticate(username=xxx, password=xxx)
                - login(request, user_obj)
            
        2. 验证码
            1. PIL模块的使用
            2. from io import BytesIO      --> 查一下
                io_obj = BytesIO()
                io_obj.getvalue()          --> 从io对象取值的方法

        3. 多对多的三种方式
            1. ManyToManyField自动生成第三张表的方式
                1. 优势
                有连表操作的快捷方法
                    1. all()
                    2. add(obj)
                    3. remove()
                    4. set([])
                    5. clear()
                2. 劣势
                    第三章关系表的字段是固定的,没有办法扩展
                    
            2. 自己创建第三张表
               在第三章表中分别通过外键关联两张表
                1. 优势
                    可以添加自定义的其他字段
                2. 劣势
                    跨表查询比较繁琐(需要跨三张表查询)
            3. 自己创建第三张表,在ManyToManyField字段中通过through和through_fields两个属性进行配置
                1. 优势:
                    1. 在关系表中可以添加自定义的其他字段
                    2. 可以使用快捷查询方法:.all()
            
        4. JS的正则
            1. 生成RegExp对象的方式
            
            2. 简写方式

今天是写注册的功能。

 首先是在form组件中写注册的表单类:

forms.py代码:

from django.core.validators import RegexValidator
from django.core.exceptions import ValidationError

#注册 Form类
class RegisterForm(forms.Form):
    username = forms.CharField(
        label='用户名',
        min_length=4,
        error_messages={
            'required':'用户名不得为空',
            'min_length':'用户名不得少于4位',
        },
        widget=forms.widgets.TextInput(attrs={'class':'form-control'})
    )
    password = forms.CharField(
        label='密码',
        min_length=6,
        error_messages={
            'required':'密码不能为空',
            'min_length':'密码不得少于6位',
        },
        widget=forms.widgets.PasswordInput(
            attrs={'class':'form-control'}
        )
    )
    re_password = forms.CharField(
        label='确认密码',
        min_length=6,
        error_messages={
            'required': '密码不能为空',
            'min_length': '密码不得少于6位',
        },
        widget=forms.widgets.PasswordInput(
            attrs={'class': 'form-control'}
        )
    )
    phone = forms.CharField(
        label='手机号',
        min_length=11,
        error_messages={
            'required':'手机号不能为空',
        },
        validators=[RegexValidator(r'1[3-9]\d{9}', "手机号码格式不正确")],
        widget=forms.widgets.TextInput(
            attrs={"class": "form-control"}
        )
    )
    email = forms.CharField(
        label='邮箱',
        error_messages={
            'required':'邮箱不能为空',
        },
        validators=[RegexValidator(r'^[a-zA-Z0-9_.-]+@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*\.[a-zA-Z0-9]{2,6}$', "邮箱格式不正确")],
        widget=forms.widgets.EmailInput(
            attrs={"class": "form-control"}
        )
    )


    # 全局钩子  用来验证密码和确认密码两个字段是否相等
    def clean(self):
        pwd = self.cleaned_data.get('password')
        re_pwd = self.cleaned_data.get('re_password')
        if re_pwd and re_pwd == pwd:
            return self.cleaned_data
        else:
            self.add_error('re_password','两次密码不一致')
            raise ValidationError('两次密码不一致')

然后再urls.py中写路由

 url(r'^register/',views.Register.as_view()),

在views.py中写CBV的视图函数(简单些):

class Register(views.View):
    def get(self,request):
        form_obj = RegisterForm()
        return render(request,'register.html',{'form_obj':form_obj})

    def post(self,request):
        pass

在搭建register的html页面:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>欢迎注册</title>
    <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.css">
</head>
<body>
<div class="container">
    <div class="row">
        <div class="col-md-6 col-md-offset-3">
            <form>
                <div class="form-group">
                    <label for="{{ from_obj.username.id_for_label }}">{{ form_obj.username.label }}</label>
                    {{ form_obj.username }}
                    <span class="help-block"></span>
                </div>
                <div class="form-group">
                    <label for="{{ form_obj.password.id_for_label }}">{{ form_obj.password.label }}</label>
                    {{ form_obj.password }}
                    <span class="help-block"></span>
                </div>
                <div class="form-group">
                    <label for="{{ form_obj.re_password.id_for_label }}">{{ form_obj.re_password.label }}</label>
                    {{ form_obj.re_password }}
                    <span class="help-block"></span>
                </div>
                <div class="form-group">
                    <label for="{{ form_obj.phone.id_for_label }}">{{ form_obj.phone.label }}</label>
                    {{ form_obj.phone }}
                    <span class="help-block"></span>
                </div>
                <div class="form-group">
                    <label for="{{ form_obj.email.id_for_label }}">{{ form_obj.email.label }}</label>
                    {{ form_obj.email }}
                    <span class="help-block"></span>
                </div>
                <button type="button" class="btn btn-default">注册</button>
            </form>
        </div>
    </div>
</div>
<script src="/static/js/jquery.js"></script>
<script>
</script>
</body>
</html>

等这些简单的都做好了在一步一步往里面补充内容.

views.py代码:

# 注册
class Register(views.View):
    def get(self,request):
        form_obj = RegisterForm()
        return render(request,'register.html',{'form_obj':form_obj})

    def post(self,request):
        res = {'code':0}
        # print(request.POST)
        v_code = request.POST.get('v_code','')
        # print(v_code)
        # 先进行验证码的校验
        if v_code.upper() == request.session.get('v_code'):
            form_obj = RegisterForm(request.POST)
            # 验证码正确
            if form_obj.is_valid(): #数据校验
                print(form_obj.cleaned_data)
                # 删除不需要的数据
                form_obj.cleaned_data.pop('re_password')
                models.UserInfo.objects.create_user(**form_obj.cleaned_data)
                # 创建完了,进入登陆
                res['msg'] = '/login/'
            else:
                #用户填写的信息不正经
                res['code'] = 1
                res['msg'] = form_obj.errors # 拿到所有的错误信息
        else:
            res['code'] = 2
            res['msg'] = '验证码错误'
        return  JsonResponse(res)

html代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>欢迎注册</title>
    <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.css">
</head>
<body>
{% csrf_token %}
<div class="container">
    <div class="row">
        <div class="col-md-6 col-md-offset-3">
            <form>
                <div class="form-group">
                    <label for="{{ from_obj.username.id_for_label }}">{{ form_obj.username.label }}</label>
                    {{ form_obj.username }}
                    <span class="help-block"></span>
                </div>
                <div class="form-group">
                    <label for="{{ form_obj.password.id_for_label }}">{{ form_obj.password.label }}</label>
                    {{ form_obj.password }}
                    <span class="help-block"></span>
                </div>
                <div class="form-group">
                    <label for="{{ form_obj.re_password.id_for_label }}">{{ form_obj.re_password.label }}</label>
                    {{ form_obj.re_password }}
                    <span class="help-block"></span>
                </div>
                <div class="form-group">
                    <label for="{{ form_obj.phone.id_for_label }}">{{ form_obj.phone.label }}</label>
                    {{ form_obj.phone }}
                    <span class="help-block"></span>
                </div>
                <div class="form-group">
                    <label for="{{ form_obj.email.id_for_label }}">{{ form_obj.email.label }}</label>
                    {{ form_obj.email }}
                    <span class="help-block"></span>
                </div>
                <div class="form-group">
                    <label for="v_code">验证码</label>
                    <input type="text" id="v-code" class="form-control" style="width: 250px; height:35px;display: inline-block">
                    <img src="/v_code/" alt="">
                    <span id="error-p" class="err-text"></span>
                </div>
                <button id="reg-btn" type="button" class="btn btn-success">注册</button>
            </form>
        </div>
    </div>
</div>
<script src="/static/js/jquery.js"></script>
<script>
    $('#reg-btn').click(function () {
        //取到用户填写的数据
        var username = $('#id_username').val();
        var pwd = $('#id_password').val();
        var re_pwd = $('#id_re_password').val();
        var phone = $('#id_phone').val();
        var email = $('#id_email').val();
        var v_code = $('#v-code').val();
        var csrfToken = $("[name='csrfmiddlewaretoken']").val();
        //发送请求
        $.ajax({
            url:'/register/',
            type:'post',
            data:{
                username:username,
                password:pwd,
                re_password:re_pwd,
                phone:phone,
                email:email,
                v_code:v_code,
                csrfmiddlewaretoken:csrfToken,
            },
            success:function (res) {
{#                console.log(res);#}
                //验证码有误
                if(res['code'] === 2){
                    $('#error-p').text(res['msg'])
                    //注册成功
                }else if(res.code === 0){
                    location.href = res.msg
                    //用户信息有误
                }else if(res.code === 1){
                    console.log(res.msg);
                    $.each(res.msg,function (k,v) {
                        $('#id_'+k).next().text(v[0]).parent().addClass('has-error')
                    })
                }
            }
        })

    });
    // 每一个input标签获取焦点的时候,把自己下面的span标签内容清空,把父标签的has-error样式移除
    $('input.form-control').focus(function () {
        $(this).next('span').text('').parent().removeClass('has-error')
    });
    $("#v-code").focus(function () {
        $(this).val('').next().next().text('');
    });
</script>
</body>
</html>

这就是注册的功能。

现在我们需要在注册的功能上加上用户选择头像的功能

这时候我们就需要在html上加上这样一个div

<div class="form-group">
<label for="avatar">头像</label>
<img id="avatar-img" src="/static/img/default.png" alt="" style="height: 80px;width: 80px;margin-left: 15px">
<input type="file" accept="image/*" id="avatar" >
</div>

这样页面上的效果是这样的这必然不是我们想要的,我们想要的是我们点击图片时就可以选择头像。所以最后我们将img标签放在label标签内就可以了。

当我们选择头像时,实现在页面上的预览就需要加上jQuery操作了。

//前端页面实现头像预览
    //当用户选中文件之后,也就是头像的input标签有值时触法
    $('#avatar').change(function () {
        //找到用户选中的文件
        var file = this.files[0];
        //console.log(this.files,typeof this.files);
        //生成一个读文件的对象
        var fr = new FileReader();
        //从文件中读取头像文件数据
        fr.readAsDataURL(file);
        //读取文件之后
        fr.onload = function () {
            //将img标签的src更换成我选中的那个文件的地址
            $('#avatar-img').attr('src',fr.result)
        }
    })

这样就可以了。

虽然在页面上是可以展现出来了,但是我们需要把他发送到后端去,这样发送ajax请求时的jQuery操作就有改变了:

$("#reg-btn").click(function () {
        // 1. 取到用户填写的数据
        var fd = new FormData();
        fd.append("username", $("#id_username").val());
        fd.append("password", $("#id_password").val());
        fd.append("re_password", $("#id_re_password").val());
        fd.append("phone", $("#id_phone").val());
        fd.append("email", $("#id_email").val());
        fd.append("v_code", $("#v-code").val());
        fd.append("csrfmiddlewaretoken", $("[name='csrfmiddlewaretoken']").val());
        fd.append('avatar', $("#avatar")[0].files[0]);
        // 2. 往后端发post请求
        $.ajax({
            url: '/reg/',
            type: 'post',
            data: fd,
            processData: false,
            contentType: false,
            success:function (res) {
                console.log(res);
                if (res.code === 2){
                    // 验证码有错误
                    $("#error-p").text(res.msg);
                }else if (res.code === 0){
                    // 注册成功
                    location.href = res.msg;
                }else if (res.code === 1){
                    console.log(res.msg);
                    // 遍历取出所有的错误提示信息,在页面上展示出来
                    $.each(res.msg, function (k,v) {
                        $("#id_"+k).next().text(v[0]).parent().addClass('has-error');
                    })
                }
            }
        })
    });

views,py中注册类就需要接受头像文件:

# 注册
class RegView(views.View):
    def get(self, request):
        form_obj = RegisterForm()
        return render(request, "register.html", {"form_obj": form_obj})

    def post(self, request):
        res = {"code": 0}
        print(request.POST)
        # 先进行验证码的校验
        v_code = request.POST.get("v_code", "")
        if v_code.upper() == request.session.get("v_code"):
            # 验证码正确
            form_obj = RegisterForm(request.POST)
            # 使用form做校验
            if form_obj.is_valid():
                # 数据有效
                # 1. 注册用户
                print(form_obj.cleaned_data)
                # 注意移除不需要的re_password
                form_obj.cleaned_data.pop("re_password")
                # 拿到用户上传的头像文件
                avatar_file = request.FILES.get("avatar")
                models.UserInfo.objects.create_user(**form_obj.cleaned_data, avatar=avatar_file)
                # 登录成功之后跳转到登录页面
                res["msg"] = '/login/'
            else:
                # 用户填写的数据不正经
                res["code"] = 1
                res["msg"] = form_obj.errors  # 拿到所有字段的错误提示信息
        else:
            res["code"] = 2
            res["msg"] = '验证码错误'
        return JsonResponse(res)

现在我们将这个头像展现在登陆之后的index页面中去

    页面中的用户名用{{ request.user.username }}显示,头像用{{ request.user.avatar }} 显示,但是在显示头像时,需要配置setting文件,和urls.py文件

在settings文件中配置:

#用户上传的文件配置
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR,'media')

urls.py文件中配置:

from django.views.static import serve
from django.conf import settings

#给用户上传文件配置一个处理的路由
    url(r'^media/(?P<path>.*)',serve,{'document_root':settings.MEDIA_ROOT}),

头像显示时 “/media/{{ request.user.avatar }} " 表示。这样是告诉django从/media/的目录找,这样头像就能显示出来了.

猜你喜欢

转载自www.cnblogs.com/yb635238477/p/9474624.html