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:
-
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.
-
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.
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
-
Flow chart
-
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:
|
Explain | |
|
GET | |
url definition | /image_code/ | |
Parameter format | Query parameters |
Description of parameters:
Parameter name | type | Is it necessary? | describe | |
rand | Character string | no |
|
Return result: Verification code picture
2. Backend code
-
Copy the verification code generation module to the root directory utils folder
-
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)
-
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')
-
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'), ]
- 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
-
Interface Description:
Category Explain Request method GET url definition /user/register/ Parameter format - Return result: Registration page
2. Backend code
-
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')
- user/urls.py
from django.urls import path, include from . import views app_name = 'user' urlpatterns = [ path('register/', views.RegisterView.as_view(), name='register') ]
- Root urls.py
from django.urls import path, include urlpatterns = [ path('', include('news.urls')), path('user/', include('user.urls')) ]
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 ></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 %}
-
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 |
|
|
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
-
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
-
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)
- 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 ></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
-
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)
- 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'), ]
- 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
-
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)
- 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.')
- 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