Django Project: 3. User Registration Function

Posted by and1c on Mon, 16 Sep 2019 15:46:14 +0200

Supplementary Knowledge Points for the Content of this Chapter

Good order for importing libraries:

1. System libraries 2.django libraries 3. Self-defined libraries (third-party libraries)

 

redis caches database data call fast, but it is not conducive to long-term storage.

mysql is used for long-term storage, but calls are slow.

The session session session stores content (in dictionary form) in the redis cache and sets the expiration time

 

User Registration Function

I. User Model Design

1. User Table Field Analysis

  • User name

  • Password

  • Cell-phone number

  • mailbox

2. User Model Design

django's strength lies in its high efficiency of development and its built-in permission module and many other common functions. When starting a new django project, if the User model in the permission module does not meet the project requirements, we need to extend or customize the User model.

There are two ways to extend the User model:

  1. If you don't need to change the content of the database storage, just change the behavior, then you can build a proxy model based on the User model.

  2. If you want to store the information associated with the User model, you can use OneToOneField to the model that contains other information fields. This one-to-one model is often referred to as the Profile model because it may store non-authenticated information about site users. For example:

    from django.contrib.auth.models import User
    
    class Employee(models.Model):
        user = models.OneToOneField(User, on_delete=models.CASCADE)
        department = models.CharField(max_length=100)

Custom User Model:

If you don't want to use django's built-in permission system, of course you need to customize the user model, which is not discussed. Of course, this is not recommended. The built-in privilege system of Django has a large self-defined function extension, rather than repeating the wheel.

Open a new project, the official strongly recommended user-defined user model, that is, the default user model is sufficient at present, but may be extended in the future.

from django.contrib.auth.models import AbstractUser

class User(AbstractUser):
    pass

Note: Don't forget to set AUTH_USER_MODEL in settings.py to point to it.

Once a database table has been created, it is much more difficult to modify AUTH_USER_MODEL because it affects foreign keys and many-to-many relationships. This change can't be done automatically. It needs to be repaired manually.

Official documents

3. User Model Code

Based on the above analysis, our user model code is as follows:

from django.db import models
from django.contrib.auth.models import AbstractUser, UserManager as _UserManager


class UserManager(_UserManager):
    """
    //Custom user manager modification when using the `python management.py create superuser` command
    //Can provide email
    """
    def create_superuser(self, username, password, email=None, **extra_fields):
        return super().create_superuser(username=username, password=password, email=email, **extra_fields)


class User(AbstractUser):
    """
    add mobile, email_active fields to Django user model.
    """
    mobile = models.CharField('Cell-phone number', max_length=11, unique=True, help_text='Cell-phone number', error_messages={'unique': 'This mobile phone number has been registered'})

    email_active = models.BooleanField('Mailbox status', default=False)

    class Meta:
        db_table = 'tb_user'    # Specify the database table name
        verbose_name = 'user'     # stay admin Display name in site
        verbose_name_plural = verbose_name  # Display complex number

    def __str__(self):
        return self.username

    # A list of the field names that will be prompted for
    # when create a user via createsuperuser management command.
    REQUIRED_FIELDS = ['mobile']
    # specify manager
    objects = UserManager()

Add the following configuration to the settings.py file:

# Custom User Model
AUTH_USER_MODEL = 'user.User'

Then run the command to migrate the database:

# 1. Equivalent to that app Set up migrations Catalogue and record all your information about it modes.py Changes, such as 0001_initial.py, But this change hasn't worked on the database file yet. You can open the file manually and see what's in it.
python manage.py makemigrations

# 2. Act this change on a database file, such as generating table Such
python manage.py migrate

Create another admin user

(tzproject) ~/code/tztz$ python manage.py createsuperuser
User name: admin
Mobile number: 158xxxxxxxx
Password: 
Password (again): 
The password length is too short. The password must contain at least eight characters.
This password is too common.
Bypass password validation and create user anyway? [y/N]: y
Superuser created successfully.

1. Design of Interface

  • Analyse the business logic, make it clear that there are several related sub-businesses involved in this business, and design an interface for each sub-business party group.

  • Analyse the function and task of the interface, clarify the access mode and return data of the interface:

    • Request mode of interface, such as GET, POST, PUT, etc.

    • URL Path Definition of Interface

    • Need to accept parameters and parameter formats (such as path parameters, query string, request form, JSON, etc.)

    • Data returned and data format

2. Analysis of Registration Function

  1. Flow chart

 

 

   

  1. function

Summarizing the registration business according to the flow chart includes the following functions

  • Registration page

  • Picture Verification Code

  • User name checking for registration

  • Whether to Register for Mobile Number Detection

  • Short Message Verification Code

  • Register and save user data

Because the picture verification code and the short message verification code may be used in other business in the future, the verification code function will be separated and a new application verification will be created.

3. Realization of Graphic Verification Code Function

1. Interface design

Interface Description:

Category
Explain
Request method
GET
url definition /image_code/
Parameter format Query parameters

Description of parameters:

Parameter name type Is it necessary? describe
rand Character string no
Input username

Return result: Verification code picture

2. Backend code

  1. Copy the verification code generation module to the root directory utils folder

  2. Create a new app verification dedicated to handling validation

    cd ~/code/tztz/apps/
    python ../manage.py startapp verification

Don't forget to register app in settings file

You must install pillow here before you can use chptcha (pip install pillow)

  1. The constants.py (file for setting constants) and verification/views.py code are as follows:

    # constants.py file
    # Save Settings Constants, Unit Seconds
    IMAGE_CODE_EXPIRES = 300
    # views.py file
    import logging
    
    from django.http import HttpResponse
    
    from utils.captcha.captcha import captcha
    from . import constants  # First of all, Ben. app Create in constants.py file
    # Logger
    logger = logging.getLogger('django')
    
    
    def image_code_view(request):
        """
        //Generating Picture Verification Code
        url:/image_code/
        :param request:
        :return:
        """
        text, image = captcha.generate_captcha()
        request.session['image_code'] = text
        # Save the validation code in session in
        request.session.set_expiry(constants.IMAGE_CODE_EXPIRES)
        logger.info('Image code:{}'.format(text))
    
        return HttpResponse(content=image, content_type='image/jpg')

     

  2. The verification/urls.py code is as follows:

    from django.urls import path
    from . import views
    # url Namespace
    app_name = 'verification'
    
    urlpatterns = [
        path('image_code/', views.image_code_view, name='image_code'),
    ]
  3. The root urls.py code is as follows:
    from django.urls import path, include
    
    urlpatterns = [
        path('', include('news.urls')),
        path('', include('verification.urls')),
    ]

    Trend diagram of verification code:

     

     

     

IV. Registration Page

1. Interface design

  1. Interface Description:

    Category
    Explain
    Request method
    GET
    url definition
      /user/register/
    Parameter format  
  2. Return result: Registration page

2. Backend code

  1. user/views.py

    from django.shortcuts import render
    from django.views import View
    
    
    class RegisterView(View):
        def get(self, request):
            return render(request, 'user/register.html')

     

  2. user/urls.py
    from django.urls import path, include
    from . import views
    app_name = 'user'
    
    urlpatterns = [
        path('register/', views.RegisterView.as_view(), name='register')
    ]

     

  3. Root urls.py
    from django.urls import path, include
    
    urlpatterns = [
        path('', include('news.urls')),
        path('user/', include('user.urls'))
    ]

     

3. Front-end page code

  1. The user/register.html code is as follows:

    {% extends 'base/base.html' %}
    {% load static %}
    {% block title %}register{% endblock title %}
    
    {% block link %}
    <link rel="stylesheet" href="{% static 'css/user/auth.css' %}">
    {% endblock link %}
    
    {% block main_start %}
        <main id="container">
      <div class="register-contain">
        <div class="top-contain">
          <h4 class="please-register">Please register</h4>
          <a href="javascript:void(0);" class="login">Login immediately &gt;</a>
        </div>
        <form action="" method="post" class="form-contain">
    
    
          <div class="form-item">
            <input type="text" placeholder="enter one user name" name="username" class="form-control" autocomplete="off">
          </div>
          <div class="form-item">
            <input type="password" placeholder="Please input a password" name="password" class="form-control">
          </div>
          <div class="form-item">
            <input type="password" placeholder="Please enter a confirmation password." name="password_repeat" class="form-control">
          </div>
          <div class="form-item">
            <input type="tel" placeholder="Please enter your cell phone number." name="telephone" class="form-control" autocomplete="off" autofocus>
          </div>
          <div class="form-item">
            <input type="text" placeholder="Please enter the Graphic Verification Code" name="captcha_graph" class="form-captcha">
            <a href="javascript:void(0);" class="captcha-graph-img">
              <img src="{% url 'verification:image_code' %}" alt="Verification Code" title="Click refresh">
            </a>
          </div>
          <div class="form-item">
            <input type="text" placeholder="Please enter SMS Verification Code" name="sms_captcha" class="form-captcha" autocomplete="off">
            <a href="javascript:void(0);" class="sms-captcha" title="Send Verification Code">Getting Short Message Verification Code</a>
          </div>
          <div class="form-item">
            <input type="submit" value="Immediate registration" class="register-btn">
          </div>
        </form>
      </div>
    </main>
    {% endblock main_start %}
    {% block script %}
        <script src="{% static 'js/user/auth.js' %}"></script>
    {% endblock script %}

     

  2. js code

    Click on the validation code picture to refresh the js code as follows:

    $(function () {
        let $img = $('.form-contain .form-item .captcha-graph-img img');
        
        // 1.Click Refresh Image Verification Code
        $img.click(function () {
            $img.attr('src', '/image_code/?rand=' + Math.random())
        });
    });

     

5. Design of json response data structure

1. Structural Design

The actual project is multi-person collaborative development, especially front-end and back-end interaction, back-end return data structure to be consistent.

{"errno": "0", "errmsg": "OK", "data": {...}}
field type Explain
errno Character string
Error coding
errmsg Character string error message
data   Return data

Create the res_code.py file under the utils folder in the project root directory to define the error code, which is as follows:

class Code:
    OK = "0"
    DBERR = "4001"
    NODATA = "4002"
    DATAEXIST = "4003"
    DATAERR = "4004"
    METHERR = "4005"
    SMSERROR = "4006"
    SMSFAIL = "4007"

    SESSIONERR = "4101"
    LOGINERR = "4102"
    PARAMERR = "4103"
    USERERR = "4104"
    ROLEERR = "4105"
    PWDERR = "4106"

    SERVERERR = "4500"
    UNKOWNERR = "4501"


error_map = {
    Code.OK: "Success",
    Code.DBERR: "Database query error",
    Code.NODATA: "No data",
    Code.DATAEXIST: "Data already exists",
    Code.DATAERR: "data error",
    Code.METHERR: "Method error",
    Code.SMSERROR: "Send SMS Verification Code Exception",
    Code.SMSFAIL: "Failed to send SMS Verification Code",

    Code.SESSIONERR: "User not logged in",
    Code.LOGINERR: "User login failure",
    Code.PARAMERR: "Parameter error",
    Code.USERERR: "User does not exist or is not activated",
    Code.ROLEERR: "User identity error",
    Code.PWDERR: "Password error",

    Code.SERVERERR: "internal error",
    Code.UNKOWNERR: "unknown error",
}

2. Quick Ways

To facilitate the definition of a shortcut, create a json_res.py file in the utils directory (or add it directly to the res_code file) with the following code:

from django.http import JsonResponse

# stay res_code You don't need to add the following import to the file
from .res_code import Code


def json_response(errno=Code.OK, errmsg='', data=None, kwargs=None):
json_dict = {
        'errno': errno,
        'errmsg': errmsg,
        'data': data
    }
    # Extension of additional fields
    if kwargs and isinstance(kwargs, dict) :
        json_dict.update(kwargs)
    
    return JsonResponse(json_dict)

6. Realization of User Registration Function

1. Interface design

Interface Description:

Category Explain
Request method GET
url definition /username/(?P<username>\w{5,20})/
Parameter format url path parameters

Description of parameters:

Parameter name type Is it necessary? describe
username Character string yes Input username

Returns the result:

{
    "errno": "0", 
     "errmsg": "OK",                     # error message
     "data": {
        "username": "username",            # User name for query
        "count": 1                        # Number of user name queries
    }
}

2. Backend code

  1. Creating a new app verification is specifically designed to handle validation (which has been created in the graphical validation code above, so this is redundant)

    cd ~/code/tztz/apps/
    python ../manage.py startapp verification
  2. verification/views.py code

    from user.models import User
    from utils.json_res import json_response
    
    
    def check_username_view(request, username):
        """
        //Check User Name
        url: /username/(?p<username>\w{5,20})/
        """
        data = {
            'username': username,
            'count': User.objects.filter(username=username).count()
        }
    
        return json_response(data=data)

     

  3. verification/urls.py code
    from django.urls import path, re_path
    from . import views
    # url Namespace
    app_name = 'verification'
    
    urlpatterns = [
        path('image_code/', views.image_code_view, name='image_code'),
        re_path('username/(?P<username>\w{5,20})/', views.check_username_view, name='check_username'),
    ]

     

3. Front-end page code

The user/register.html code is as follows:

{% extends 'base/base.html' %}
{% load static %}
{% block title %}register{% endblock title %}

{% block link %}
<link rel="stylesheet" href="{% static 'css/user/auth.css' %}">
{% endblock link %}

{% block main_start %}
    <main id="container">
  <div class="register-contain">
    <div class="top-contain">
      <h4 class="please-register">Please register</h4>
      <a href="javascript:void(0);" class="login">Login immediately &gt;</a>
    </div>
    <form action="" method="post" class="form-contain">


      <div class="form-item">
        <input type="text" placeholder="enter one user name" id="username" name="username" class="form-control" >
      </div>
      <div class="form-item">
        <input type="password" placeholder="Please input a password" name="password" class="form-control">
      </div>
      <div class="form-item">
        <input type="password" placeholder="Please enter a confirmation password." name="password_repeat" class="form-control">
      </div>
      <div class="form-item">
        <input type="tel" placeholder="Please enter your cell phone number." name="telephone" class="form-control" autocomplete="off">
      </div>
      <div class="form-item">
        <input type="text" placeholder="Please enter the Graphic Verification Code" name="captcha_graph" class="form-captcha">
        <a href="javascript:void(0);" class="captcha-graph-img">
          <img src="{% url 'verification:image_code' %}" alt="Verification Code" title="Click refresh">
        </a>
      </div>
      <div class="form-item">
        <input type="text" placeholder="Please enter SMS Verification Code" name="sms_captcha" class="form-captcha" autocomplete="off">
        <a href="javascript:void(0);" class="sms-captcha" title="Send Verification Code">Getting Short Message Verification Code</a>
      </div>
      <div class="form-item">
        <input type="submit" value="Immediate registration" class="register-btn">
      </div>
    </form>
  </div>
</main>
{% endblock main_start %}

{% block script %}
    <script src="{% static 'js/user/auth.js' %}"></script>
{% endblock script %}

4. Front-end js code

user/auth.js code:

$(function () {
    // Define state variables
    let isUsernameReady = false,
        isPasswordReady = false,
        isMobileReady = false,
        isSmsCodeReady = false;
    // 1.Click Refresh Image Verification Code
    let $img = $('.form-contain .form-item .captcha-graph-img img');
    

    $img.click(function () {
        $img.attr('src', '/image_code/?rand=' + Math.random())
    });

    // 2.Mouse off user name input box to verify user name
    let $username = $('#username');
    $username.blur(fnCheckUsername);
    
    function fnCheckUsername () {
        isUsernameReady = false;
        let sUsername = $username.val();    //Get the user string
        if (sUsername === ''){
            message.showError('User name cannot be empty!');
            return
        }
        if (!(/^\w{5,20}$/).test(sUsername)){
            message.showError('Please input 5-20 User Name of 2 Characters');
            return
        }
        $.ajax({
            url: '/username/' + sUsername + '/',
            type: 'GET',
            dataType: 'json',
            success: function (data) {
                if(data.data.count !== 0){
                    message.showError(data.data.username + 'Registered, please re-enter!')
                }else {
                    message.showInfo(data.data.username + 'Can be used normally!')
                    isUsernameReady = true
                }
            },
            error: function (xhr, msg) {
                message.showError('Server timeout, please try again!')
            }
        });
    }

    // 3.Check for password consistency
    let $passwordRepeat = $('input[name="password_repeat"]');
    $passwordRepeat.blur(fnCheckPassword);

    function fnCheckPassword () {
        isPasswordReady = false;
        let password = $('input[name="password"]').val();
        let passwordRepeat = $passwordRepeat.val();
        if (password === '' || passwordRepeat === ''){
            message.showError('Password cannot be empty');
            return
        }
        if (password !== passwordRepeat){
            message.showError('Two inconsistent password input');
            return
        }
        if (password === passwordRepeat){
            isPasswordReady = true
        }
    }

 

7. Judging whether the mobile phone number is registered or not

1. Interface design

Interface Description:

Category Explain
Request method GET
url definition /mobile/(?P<mobile>\1[3-9]\d{9})/
Parameter format url path parameters

Description of parameters:

Parameter name type Is it necessary? describe
moblie Character string yes Input mobile phone number

Returns the result:

{
    "errno": "0", 
     "errmsg": "OK", 
     "data": {
        "mobile": "13xxxxxxxxx",            # Inquiry Mobile Number
        "count": 1                        # Number of mobile phone number queries
    }
}

2. Backend code

  1. verification/views.py code

    # ····
    def check_mobile_view(request, mobile):
        """
        //Check the existence of mobile phone number
        url:/moblie/(?P<moblie>1[3-9]\d{9})/
        :param request:
        :param username:
        :return:
        """
        data = {
            'mobile': mobile,
            'count': User.objects.filter(mobile=mobile).count()
        }
    
        return json_response(data=data)

     

  2. verification/urls.py
    from django.urls import path, re_path
    from . import views
    # url Namespace
    app_name = 'verification'
    
    urlpatterns = [
        path('image_code/', views.image_code_view, name='image_code'),
        re_path('username/(?P<username>\w{5,20})/', views.check_username_view, name='check_username'),
        re_path('mobile/(?P<mobile>1[3-9]\d{9})/', views.check_mobile_view, name='check_mobile'),
    ]

     

  3. Front-end js code:
    $(function () {
        // Define state variables
        let isUsernameReady = false,
            isPasswordReady = false,
            isMobileReady = false,
            isSmsCodeReady = false;
        // 1.Click Refresh Image Verification Code
        let $img = $('.form-contain .form-item .captcha-graph-img img');
        
    
        $img.click(function () {
            $img.attr('src', '/image_code/?rand=' + Math.random())
        });
    
        // 2.Mouse off user name input box to verify user name
        let $username = $('#username');
        $username.blur(fnCheckUsername);
    
        function fnCheckUsername () {
            isUsernameReady = false;
            let sUsername = $username.val();    //Get the user string
            if (sUsername === ''){
                message.showError('User name cannot be empty!');
                return
            }
            if (!(/^\w{5,20}$/).test(sUsername)){
                message.showError('Please input 5-20 User Name of 2 Characters');
                return
            }
            $.ajax({
                url: '/username/' + sUsername + '/',
                type: 'GET',
                dataType: 'json',
                success: function (data) {
                    if(data.data.count !== 0){
                        message.showError(data.data.username + 'Registered, please re-enter!')
                    }else {
                        message.showInfo(data.data.username + 'Can be used normally!')
                        isUsernameReady = true
                    }
                },
                error: function (xhr, msg) {
                    message.showError('Server timeout, please try again!')
                }
            });
        }
    
        // 3.Check for password consistency
        let $passwordRepeat = $('input[name="password_repeat"]');
        $passwordRepeat.blur(fnCheckPassword);
    
        function fnCheckPassword () {
            isPasswordReady = false;
            let password = $('input[name="password"]').val();
            let passwordRepeat = $passwordRepeat.val();
            if (password === '' || passwordRepeat === ''){
                message.showError('Password cannot be empty');
                return
            }
            if (password !== passwordRepeat){
                message.showError('Two inconsistent password input');
                return
            }
            if (password === passwordRepeat){
                isPasswordReady = true
            }
        }
    
        // 4.Check whether the mobile phone number is available
        let $mobile = $('input[name="mobile"]');
        $mobile.blur(fnCheckMobile);
    
        function fnCheckMobile () {
            isMobileReady = true;
            let sMobile = $mobile.val();
            if(sMobile === ''){
                message.showError('Mobile phone number cannot be empty');
                return
            }
            if(!(/^1[3-9]\d{9}$/).test(sMobile)){
                message.showError('Incorrect format of mobile phone number');
                return
            }
    
            $.ajax({
                url: '/mobile/' + sMobile + '/',
                type: 'GET',
                dataType: 'json',
                success: function (data) {
                    if(data.data.count !== 0){
                        message.showError(data.data.mobile + 'Registered, please re-enter!')
                    }else {
                        message.showInfo(data.data.mobile + 'Can be used normally!');
                        isMobileReady = true
                    }
                },
                error: function (xhr, msg) {
                    message.showError('Server timeout, please try again!')
                }
            });
    
        }
    });

     

8. Capturing Short Message Verification Code Function

1. Business process analysis

  • Check mobile phone number

  • Check if the picture verification code is correct

  • Check whether records are sent within 60 seconds

  • Generating Short Message Verification Code

  • Sending SMS

  • Save Short Message Verification Code and Send Record

2. Interface design

Interface Description:

Category Explain
Request method POST
url definition /sms_code/
Parameter format form

Description of parameters:

Parameter name type Is it necessary? describe
moblie Character string yes Mobile phone number entered by user
captcha Character string yes Authentication Code Text Input by User

Returns the result:

{
    "errno": "0", 
     "errmsg": "Successful Sending of Short Message Verification Code!", 
}

3. Backend code

  1. The verification/views.py code is as follows:

    import logging
    import random
    
    from django.http import HttpResponse
    from django.views import View
    from django_redis import get_redis_connection
    
    from user.models import User
    from utils.json_res import json_response
    from utils.res_code import Code, error_map
    from utils.captcha.captcha import captcha
    from utils.yuntongxun.sms import CCP
    
    from . import constants
    from .forms import CheckImagForm
    
    # Logger
    logger = logging.getLogger('django')
    
    
    def image_code_view(request):
        """
        //Generating Picture Verification Code
        url:/image_code/
        :param request:
        :return:
        """
        text, image = captcha.generate_captcha()
        request.session['image_code'] = text
        # Save the validation code in session in
        request.session.set_expiry(constants.IMAGE_CODE_EXPIRES)
        logger.info('Image code:{}'.format(text))
    
        return HttpResponse(content=image, content_type='image/jpg')
    
    
    def check_username_view(request, username):
        """
        //Check whether the user name exists
        url:/username/(?P<username>\w{5,20})/
        :param request:
        :param username:
        :return:
        """
        data = {
            'username': username,
            'count': User.objects.filter(username=username).count()
        }
    
        return json_response(data=data)
    
    
    def check_mobile_view(request, mobile):
        """
        //Check the existence of mobile phone number
        url:/moblie/(?P<moblie>1[3-9]\d{9})/
        :param request:
        :param username:
        :return:
        """
        data = {
            'mobile': mobile,
            'count': User.objects.filter(mobile=mobile).count()
        }
    
        return json_response(data=data)
    
    
    class SmsCodeView(View):
        """
        //Send Short Message Verification Code
        POST /sms_codes/
        """
        def post(self, request):
            # 1.Calibration parameter
    
            form = CheckImagForm(request.POST, request=request)
            if form.is_valid():
                # 2.Get cell phone
                mobile = form.cleaned_data.get('mobile')
                # 3.Generating Mobile Phone Verification Code
                sms_code = ''.join([random.choice('0123456789') for _ in range(constants.SMS_CODE_LENGTH)])
                # 4.Send mobile phone authentication code
                ccp = CCP()
                try:
                    res = ccp.send_template_sms(mobile, [sms_code, constants.SMS_CODE_EXPIRES], "1")
                    if res == 0:
                        logger.info('Send Short Message Verification Code[normal][mobile: %s sms_code: %s]' % (mobile, sms_code))
                    else:
                        logger.error('Send Short Message Verification Code[fail][moblie: %s sms_code: %s]' % (mobile, sms_code))
                        return json_response(errno=Code.SMSFAIL, errmsg=error_map[Code.SMSFAIL])
                except Exception as e:
                    logger.error('Send Short Message Verification Code[abnormal][mobile: %s message: %s]' % (mobile, e))
                    return json_response(errno=Code.SMSERROR, errmsg=error_map[Code.SMSERROR])
    
    
                # 5.Save to redis data base
                # Create SMS Verification Code Sending Record
                sms_flag_key = 'sms_flag_{}'.format(mobile)
                # Creating Content Record of Short Message Verification Code
                sms_text_key = 'sms_text_{}'.format(mobile)
    
                redis_conn = get_redis_connection(alias='verify_code')
                pl = redis_conn.pipeline()
    
                try:
                    pl.setex(sms_flag_key, constants.SMS_CODE_INTERVAL, 1)
                    pl.setex(sms_text_key, constants.SMS_CODE_EXPIRES*60, sms_code)
                    # Let Pipeline Notify redis Executive order
                    pl.execute()
                    return json_response(errmsg="Message Verification Code Sent Successfully!")
                except Exception as e:
                    logger.error('redis Execution exception:{}'.format(e))
    
                    return json_response(errno=Code.UNKOWNERR, errmsg=error_map[Code.UNKOWNERR])
    
            else:
                # Stitching the form error information
                err_msg_list = []
                for item in form.errors.get_json_data().values():
                    err_msg_list.append(item[0].get('message'))
                    # print(item[0].get('message'))   # for test
                err_msg_str = '/'.join(err_msg_list)  # Splicing error information as a string
    
                return json_response(errno=Code.PARAMERR, errmsg=err_msg_str)
  2. The verification/forms.py file code is as follows:
    from django import forms
    from django.core.validators import RegexValidator
    from django_redis import get_redis_connection
    
    from user.models import User
    
    # Create a Regular Checker for Mobile Phone Numbers
    mobile_validator = RegexValidator(r'^1[3-9]\d{9}$', 'Incorrect format of mobile phone number')
    
    
    class CheckImagForm(forms.Form):
        """
        check image code
        """
    
        def __init__(self, *args, **kwargs):
            self.request = kwargs.pop('request')
            super().__init__(*args, **kwargs)
    
        mobile = forms.CharField(max_length=11, min_length=11, validators=[mobile_validator, ],
                                 error_messages={
                                     'max_length': 'Error in length of mobile phone',
                                     'min_length': 'Error in length of mobile phone',
                                     'required': 'Mobile phone number cannot be empty'
                                 })
    
        captcha = forms.CharField(max_length=4, min_length=4,
                                  error_messages={
                                      'max_length': 'Error in Verification Code Length',
                                      'min_length': 'Picture Verification Code Length Error',
                                      'required': 'Picture Verification Code cannot be empty'
                                  })
    
        def clean(self):
            clean_data = super().clean()
            mobile = clean_data.get('mobile')
            captcha = clean_data.get('captcha')
        # 1.Check Picture Verification Code
            image_code = self.request.session.get('image_code')
            if (not image_code) or (image_code.upper() != captcha.upper()):
                raise forms.ValidationError('Photo Verification Code failed!')
    
        # 2.Check whether text messages have been sent within 60 seconds
            redis_conn = get_redis_connection(alias='verify_code')
            if redis_conn.get('sms_flag_{}'.format(mobile)):
                raise forms.ValidationError('Getting SMS Verification Codes Too Frequently')
    
        # 3.Check whether the mobile phone number has been registered
            if User.objects.filter(mobile=mobile).count():
                raise forms.ValidationError('The mobile phone number has been registered. Please re-enter it.')

     

  3. The verification/constants.py code is as follows:
    # Photo Verification Code expiration time per second
    IMAGE_CODE_EXPIRES = 300
    
    # Short Message Verification Code Length
    SMS_CODE_LENGTH = 4
    
    # Short Message Verification Code Sending Interval Seconds
    SMS_CODE_INTERVAL = 60
    
    # Short Message Verification Code expiration time
    SMS_CODE_EXPIRES = 5
    
    # Short Message Sending Template
    SMS_CODE_TEMP_ID = 1

     

Topics: Python Mobile Django Session Database