关于django:python实战项目练习Django商城项目之注册功能实现

13次阅读

共计 6023 个字符,预计需要花费 16 分钟才能阅读完成。

设计到的前端常识

我的项目的前端页面应用 vue 来实现部分刷新,通过数据的双向绑定实现与用户的交互,上面来看一下需要,在用户输出内容后,前端须要做一些简略的规定校验,咱们心愿在在用户输出后可能实时检测,如果有谬误可能在输入框的下方显示进去。

<li>
    <label> 用户名:</label>
    <input type="text" name="username" id="user_name">
    <span class="error_tip"> 请输出 5 -20 个字符的用户 </span>
</li>
<li>
    <label> 明码:</label>
    <input type="password" name="password" id="pwd">
    <span class="error_tip"> 请输出 8 -20 位的明码 </span>
</li>

下面是一个用户和明码的输入框,当用户输出完用户名当前,光标来到输入框,可能实时的检测输出内容的正确性,当输出有问题的时候,在输入框的下方显示错误信息。

v-model 实现数据的双向绑定,v-on 进行事件绑定,v-show 是管制 dom 显示与否,上面是退出 vue 后的局部代码

<li>
    <label> 用户名:</label>
    <input type="text" name="username" id="user_name" v-model="username" @blur="check_username">
    <span class="error_tip" v-show="error_name">[[error_name_message]]</span>
</li>
<li>
    <label> 明码:</label>
    <input type="password" name="password" id="pwd" v-model="password" @blur="check_password">
    <span class="error_tip" v-show="error_password"> 请输出 8 -20 位的明码 </span>
</li>

用户输出的用户名和 username 变量绑定,光标隐没触发绑定工夫 check_username,通过 v -show 绑定到布尔值变量 error_name,来管制是否显示字符串变量 error_name_message,其余的输入框都相似这种操作。

注册业务实现

前端注册业务逻辑

注册表单代码:

<form method="post" class="register_form" >
    {{csrf_input}}
    <ul>
        <li>
            <label> 用户名:</label>
            <input type="text" name="username" id="user_name" v-model="username" @blur="check_username">
            <span class="error_tip" v-show="error_name">[[error_name_message]]</span>
        </li>
        <li>
            <label> 明码:</label>
            <input type="password" name="password" id="pwd" v-model="password" @blur="check_password">
            <span class="error_tip" v-show="error_password"> 请输出 8 -20 位的明码 </span>
        </li>
        <li>
            <label> 确认明码:</label>
            <input type="password" v-model="password2" @blur="check_password2" name="password2"
                   id="cpwd">
            <span class="error_tip" v-show="error_password2"> 两次输出的明码不统一 </span>
        </li>
        <li>
            <label> 手机号:</label>
            <input type="text" v-model="mobile" @blur="check_mobile" name="mobile" id="phone">
            <span class="error_tip" v-show="error_mobile">[[error_mobile_message]]</span>
        </li>

        <li>
            <label> 图形验证码:</label>
            <input type="text" name="image_code" id="pic_code" class="msg_input">
            <img src="{{static('images/pic_code.jpg') }}" alt="图形验证码" class="pic_code">
            <span class="error_tip"> 请填写图形验证码 </span>
        </li>
        <li>
            <label> 短信验证码:</label>
            <input type="text" name="sms_code" id="msg_code" class="msg_input">
            <a href="javascript:;" class="get_msg_code"> 获取短信验证码 </a>
            <span class="error_tip"> 请填写短信验证码 </span>
        </li>
        <li class="agreement">
            <input type="checkbox" name="allow" id="allow" v-model="allow" @change="check_allow">
            <label> 批准”商城用户应用协定“</label>
            <span class="error_tip" v-show="error_allow"> 请勾选用户协定 </span>
        </li>
        <li class="reg_sub">
            <input type="submit" value="注 册" @change="on_submit">
            {% if register_errmsg %}
                <span class="error_tip2">{{register_errmsg}}</span>
            {% endif %}
        </li>
    </ul>
</form>

导入 vue.js 和 ajax 申请的 js 库

<script type="text/javascript" src="{{static('js/vue-2.5.16.js') }}"></script>
<script type="text/javascript" src="{{static('js/axios-0.18.0.min.js') }}"></script>

筹备 register.js 文件

register.js 文件次要解决注册页面的交互事件,并且向服务端提交注册表单申请

<script type="text/javascript" src="{{static('js/register.js') }}"></script>

上面是实现的前端校验逻辑以及表单提交逻辑

methods: {
    // 校验用户名
    check_username() {let re = /^[a-zA-Z0-9_-]{5,20}$/;
        if (re.test(this.username)) {this.error_name = false;} else {
            this.error_name_message = '请输出 5 -20 个字符的用户名';
            this.error_name = true;
        }
    },
    // 校验明码
    check_password() {let re = /^[0-9A-Za-z]{8,20}$/;
        this.error_password = !re.test(this.password);
    },
    // 校验确认明码
    check_password2() {if (this.password !== this.password2) {this.error_password2 = true;} else {this.error_password2 = false;}
    },
    // 校验手机号
    check_mobile() {let re = /^1[3-9]\d{9}$/;
        if (re.test(this.mobile)) {this.error_mobile = false;} else {
            this.error_mobile_message = '您输出的手机号格局不正确';
            this.error_mobile = true;
        }
    },
    // 校验是否勾选协定
    check_allow() {this.error_allow = !this.allow;},
    // 监听表单提交事件
    on_submit() {this.check_username();
        this.check_password();
        this.check_password2();
        this.check_mobile();
        this.check_allow();
                # 输出字段中有一个不合乎规定就禁止
        if (this.error_name === true || this.error_password === true || this.error_password2 === true
            || this.error_mobile === true || this.error_allow === true) {
            // 禁用表单的提交
            window.event.returnValue = false;
        }
    },
}

后端业务注册逻辑

在用户输完用户名之后,咱们往往心愿可能跟快的给出这个用户名是否合乎注册需要,后面只是对用户名的规定进行了校验,还想晓得他是否曾经在零碎注册过了,不然当用户都输完提交注册再给出用户名或者手机号曾经注册过,体验不是特地好。所以须要在光标来到用户名输入框的时候就申请服务端来判断是否注册过。

定义路由

path('register/', views.RegisterView.as_view(), name='register'),  # name 增加命名空间
path('usernames/<str:username>', views.UsernameCountView.as_view(), name="username"),
re_path(r'mobiles/(?P<mobile>1[3-9]\d{9})', views.MobileCountView.as_view(), name='mobile')

编写视图类

class UsernameCountView(View):

    def get(self, request, username):
        """
        查问该用户名是否在零碎中存在
        :param request: 申请对像
        :param username: 前端传递的用户名
        :return:
        """
        count = User.objects.filter(username=username).count()
        return http.JsonResponse({'code':1001, 'msg':'用户已存在'}) if count == 1 \
            else http.JsonResponse({'code': 1000, 'msg': ''})

这里没有对响应做对立解决封装,前面专门介绍一下。

而后就是注册视图类的编写了:

class RegisterView(View):
    """用户注册视图类"""

    def get(self, request):
        '''获取注册页面'''
        return render(request, 'register.html')

    def post(self, request):
        """"""username = request.POST.get('username')
        password = request.POST.get('password')
        password2 = request.POST.get('password2')
        mobile = request.POST.get('mobile')
        allow = request.POST.get('allow')
        # 判断参数是否齐全
        if not all([username, password, password2, mobile, allow]):
            return http.HttpResponseForbidden('短少必传参数')
        # 判断用户名是否是 5 -20 个字符
        if not re.match(r'^[a-zA-Z0-9_-]{5,20}$', username):
            return http.HttpResponseForbidden('请输出 5 -20 个字符的用户名')
        # 判断明码是否是 8 -20 个数字
        if not re.match(r'^[0-9A-Za-z]{8,20}$', password):
            return http.HttpResponseForbidden('请输出 8 -20 位的明码')
        # 判断两次明码是否统一
        if password != password2:
            return http.HttpResponseForbidden('两次输出的明码不统一')
        # 判断手机号是否非法
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return http.HttpResponseForbidden('请输出正确的手机号码')
        # 判断是否勾选用户协定
        if allow != 'on':
            return http.HttpResponseForbidden('请勾选用户协定')

        try:
            user = User.objects.create_user(username=username, password=password, mobile=mobile)
        except DatabaseError as e:
            return render(request, 'register.html', {'register_errmsg': e.args})

        # 注册胜利保留会话
        login(request, user)

        return redirect(reverse('contents:index'))

django 提供的 login 办法,封装了写入 session 的操作,帮忙咱们疾速登入一个用户,并实现状态放弃,将通过认证的用户的惟一标识信息(比方:用户 ID)写入到以后浏览器的 cookie 和服务端的 session 中。

request.session[SESSION_KEY] = user._meta.pk.value_to_string(user)
request.session[BACKEND_SESSION_KEY] = backend
request.session[HASH_SESSION_KEY] = session_auth_hash

session 会存入 redis,之前在工程创立时进行 session 存储的配置

SESSION_ENGINE = "django.contrib.sessions.backends.cache"
SESSION_CACHE_ALIAS = "session"

正文完
 0