Django--实战--2--注册模块

1 配置url路由

urlpatterns = [
    path('admin/', admin.site.urls),
    path('login/', views.login),
    path('index/', views.index),
    path('get_validCode_img/', views.get_validCode_img),
    path('register/', views.register),    # 新添加的

    # midea配置
    re_path(r"media/(?P<path>.*)$", serve, {"document_root": settings.MEDIA_ROOT})  # 新添加的,为了用户可以直接访问其头像图片

]

2 settings.py

在settings.py中添加以下配置, 为了用户可以直接访问其头像图片

MEDIA_URL = "/media/"  # 类似于STATIC_URL,django内部并未对其做路由配置,需开发人员在urls.py中做路由配置
MEDIA_ROOT = os.path.join(BASE_DIR, "media")

3 register.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="/static/blog/bs/css/bootstrap.css">
    <style>
        #avatar_img{
            margin-left: 20px;
        }

        #avatar{
            display:none
        }

        .error{
            color:red
        }
    </style>
</head>
<body>
<h3>注册页面</h3>
<div class="container">
    <div class="row">
        <div class="col-md-6 col-lg-3">
            <form id="form">   <!-- 此处用ajax提交表单,因此不需要写action属性 -->
                {% csrf_token %}
                {% for field in form %}
                    <div class="form-group">
                        <label for="{{ field.auto_id }}">{{ field.label }}</label>
                        {{ field }}<span class="error pull-right"></span>
                    </div>
                {% endfor %}
                <div class="form-group">
                    <label for="avatar">
                        头像
                        <img id="avatar_img" width="60" height="60" src="/static/blog/img/head-portrait.jpeg" alt="">
                    </label>
                    <input type="file" id="avatar">
                </div>
                <!-- 此处用ajax提交,因此使用普通按钮,不需要type="submit"的form表单指定按钮 -->
                <input type="button" class="btn btn-default reg_btn" value="submit"><span class="error"></span>

            </form>
        </div>
    </div>
</div>

<script src="/static/js/jquery-3.6.0.min.js"></script>

<script>
    $("#avatar").change(function () {  // jquery对象事件操作

        // 获取用户选中的文件对象
        var file_obj = $(this)[0].files[0];

        // 获取文件对象的路径
        var reader  = new FileReader();
        reader.readAsDataURL(file_obj);  // 异步

        // 修改img的src,src=文件对象的路径
        reader.onload = function(){   // js对象事件操作
            $("#avatar_img").attr("src", reader.result)
        }
    })

    //基于Ajax提交数据
    
    $(".reg_btn").click(function () {
        var formdata = new FormData();  // 当提交内容有文件使需要使用form-data方式
       // console.log($("#form").serializeArray());
        var request_data = $("#form").serializeArray();
        $.each(request_data, function(index, data){
            formdata.append(data.name, data.value)
        });

       // 该部分注释掉的代码与68-71行的代码功能相同
       // formdata.append("user", $("#id_user").val());
       // formdata.append("pwd", $("#id_pwd").val());
       // formdata.append("re_pwd", $("#id_re_pwd").val());
       // formdata.append("email", $("#id_email").val());
       // formdata.append("csrfmiddlewaretoken", $("[name='csrfmiddlewaretoken']").val());
        formdata.append("avatar", $("#avatar")[0].files[0]);   // 添加头像的文件对象
        //console.log($("#avatar")[0].files[0]);

        $.ajax({
            url:"",
            type:"post",
            contentType:false,    // form-data方式必须配上该参数
            processData:false,    // form-data方式必须配上该参数
            data:formdata,
            success:function (data) {
            //    console.log(data)
                if(data.user){  // 判断是否注册成功
                    // 注册成功跳转到登陆页面
                     location.href = "/login";
                }
                else{  // 注册失败
                    // console.log(data.msg)

                    // 清空上次错误信息
                    $("span").html("");

                    // 清空上次错误的相应的input边框的标红
                    $(".form-group").removeClass("has-error");

                    // 展示此次提交响应的错误信息
                    $.each(data.msg, function (field, error_list) {
                         // console.log(field, error_list);

                         if (field=="__all__"){
                             $("#id_re_pwd").next().html(error_list[0]).parent().addClass();
                         }

                         // 例如:先找到id=id_user的input标签再找它的下一个span标签
                         // 此处使用html()或text()都可以
                         $("#id_"+field).next().html(error_list[0]);

                         // 使相应的input边框变红,bootstrap提供了has-error
                         $("#id_"+field).parent().addClass("has-error");
                    })
                }
            }
        })
    })
</script>
</body>
</html>

4 myForm.py

from django import forms
from django.forms import widgets
from blog.models import UserInfo
from django.core.exceptions import NON_FIELD_ERRORS, ValidationError


class UserForm(forms.Form):
    user = forms.CharField(max_length=32,
                           label="用户名",
                           error_messages={"required": "用户名不能为空!"},  # error_messages有很多不同字段,代表不同错误
                           widget=widgets.TextInput(attrs={"class": "form-control"})
                           )
    pwd = forms.CharField(max_length=32,
                          error_messages={"required": "密码不能为空!"},
                          label="密码",
                          widget=widgets.PasswordInput(attrs={"class": "form-control"})
                          )
    re_pwd = forms.CharField(max_length=32,
                             error_messages={"required": "确认密码不能为空!"},
                             label="确认密码", widget=widgets.PasswordInput(attrs={"class": "form-control"})
                             )
    email = forms.EmailField(max_length=32,
                             error_messages={"required": "邮箱不能为空!",
                                             "invalid": "邮箱地址格式错误或不支持!",
                                             },
                             label="邮箱",
                             widget=widgets.EmailInput(attrs={"class": "form-control"})
                             )

    def clean_user(self):
        """
        Form中字段中定义的格式匹配完之后,执行此方法进行验证
        :return:
        """
        user = self.cleaned_data.get("user")  # cleaned_data已经经过字段中定义的验证
        user = UserInfo.objects.filter(username=user).first()  # 从UserInfo表中查找是否有该用户
        if not user:
            return self.cleaned_data.get("user")  # 局部钩子时返回self.cleaned_data.get("user")
        else:
            raise ValidationError("该用户已注册!")  # 若用户已注册,需要返回的错误信息提示

    def clean(self):
        """
        全局钩子
        :return:
        """
        pwd = self.cleaned_data.get("pwd")
        re_pwd = self.cleaned_data.get("re_pwd")

        if pwd and re_pwd:  # 避免 pwd 和 re_pwd 一个有另一个没有时,页面密码和确认密码后会提出两个不同的错误信息
            if pwd == re_pwd:
                return self.cleaned_data  # 全局钩子时返回self.cleaned_data
            else:
                raise ValidationError("确认密码与密码输入不一致!")
        else:
            return self.cleaned_data

5 编写register视图函数

在views.py中添加以下视图函数

from django.shortcuts import render, HttpResponse
from django.http import JsonResponse
from django.contrib import auth
from blog.models import UserInfo
from blog.myForms import UserForm


def register(request):
    """
    用户注册验证
    :param request:
    :return:
    """
    if request.is_ajax():
        # print(request.POST)

        # form组件功能2:检查字段的有效性,UserForm中的字段名必须与POST中的键名相同
        form = UserForm(request.POST)  # 创建一个form表单对象
        response = {"user": None, "msg": None}
        if form.is_valid():  # 检查form表单字段
            response["user"] = form.cleaned_data.get("user")
            # print("user", response["user"])
            # 生成一条用户记录
            user = form.cleaned_data.get("user")
            # print("user", user)
            pwd = form.cleaned_data.get("pwd")
            # print("pwd", form.cleaned_data.get("pwd"))
            email = form.cleaned_data.get("email")
            # print("email", email)
            avatar_obj = request.FILES.get("avatar")  # 通过request取文件
            # print(type(avatar_obj))
            # print("avatar_obj", avatar_obj)

            # if avatar_obj:  # 判断用户是否上传头像
            #     # 用户上传了头像
            #     user_obj = UserInfo.objects.create_user(username=user, password=pwd, email=email, avatar=avatar_obj)
            # else:  # 用户未上传头像,此时avatar_obj=None,使用默认的头像即可
            #     user_obj = UserInfo.objects.create_user(username=user, password=pwd, email=email)

            # 此段代码是对75-79代码的优化
            extra = {}
            if avatar_obj:
                extra["avatar"] = avatar_obj
            UserInfo.objects.create_user(username=user, password=pwd, email=email, **extra)
        else:
            # print(form.cleaned_data)
            # print(form.errors)
            response["msg"] = form.errors  # 已经过滤掉了csrfmiddlewaretoken和avatar
            # print(response)
        return JsonResponse(response)
    form = UserForm()  # form组件功能1:生成form表单
    return render(request, "register.html", {"form": form})

6 总结

后端任务:接受前端发送来的注册信息并对其各个字段进行验证。验证通过创建一个用户,验证不通过,给前端以json形式返回错误信息。

后端任务:通过ajax给后端发送注册信息。并对接受到的响应进行处理,若返回的是成功注册信息,则直接跳转到登录页面;若返回的是错误信息,则将错误信息渲染到页面,以提示注册人员。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值