python實戰項目練習-Django商城項目之註冊功能實現

設計到的前端知識

項目的前端頁面使用vue來實現局部刷新,經過數據的雙向綁定實現與用戶的交互,下面來看一下需求,在用戶輸入內容後,前端須要作一些簡單的規則校驗,咱們但願在在用戶輸入後可以實時檢測,若是有錯誤可以在輸入框的下方顯示出來。javascript

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

上面是一個用戶和密碼的輸入框,當用戶輸入完用戶名之後,光標離開輸入框,可以實時的檢測輸入內容的正確性,當輸入有問題的時候,在輸入框的下方顯示錯誤信息。html

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,其餘的輸入框都相似這種操做。vue

註冊業務實現

前端註冊業務邏輯

註冊表單代碼:java

<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文件主要處理註冊頁面的交互事件,而且向服務端提交註冊表單請求python

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

下面是實現的前端校驗邏輯以及表單提交邏輯ios

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;
        }
    },
}

後端業務註冊邏輯

在用戶輸完用戶名以後,咱們每每但願可以跟快的給出這個用戶名是否符合註冊需求,前面只是對用戶名的規則進行了校驗,還想知道他是否已經在系統註冊過了,否則當用戶都輸完提交註冊再給出用戶名或者手機號已經註冊過,體驗不是特別好。因此須要在光標離開用戶名輸入框的時候就請求服務端來判斷是否註冊過。ajax

定義路由redis

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

編寫視圖類django

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"
相關文章
相關標籤/搜索