flask---注冊-驗證簡單邏輯api接口


把注冊業務邏輯拆分三個接口:

注冊的本質是在服務器上新建一個資源信息,其對應的方法是post,

而圖片驗證碼的生成與獲取,短信驗證碼的生成與獲取是get請求。

從接口的風格來考慮拆分了三個。在一個也可以實現。

 

為什么前后端分離?
重點:提高(后端接口)代碼的復用性比如任意web項目都有用戶模塊,如使用Django的一些試圖類或視圖函數內容不能用了,因為其嚴重依賴於模板。如前后端分離調用接口代碼基本不變,大量的return直接返回給瀏覽器了

解耦,快速開發,責任分清,Django有MVT開發就慢了嗎,前后端不分離使用?重點就是提高(后端接口)代碼的復用性其他是附屬功能

 

生成圖片驗證碼

1 調用captcha擴展包,生成圖片驗證碼,name,text,image

2 本地存儲圖片驗證碼,使用redis數據庫(如發生異常,保存圖片驗證碼失敗,記錄日志信息)

3 返回圖片本身,設置響應的content-type(如未發生異常,則返回圖片)

實現代碼:

# coding=utf-8
# 導入藍圖對象
from . import api
# 導入圖片驗證碼擴展
from ihome.utils.captcha.captcha import captcha
# 導入數據庫實例
from ihome import redis_store,constants,db
# 導入flask內置的對象
from flask import current_app,jsonify,make_response,request,session
# 導入自定義的狀態碼
from ihome.utils.response_code import RET
# 導入模型類
from ihome.models import User
# 導入雲通訊擴展包
from ihome.utils import sms


# 導入正則模塊
import re
# 導入random模塊,構造短信隨機數
import random


@api.route('/imagecode/<image_code_id>',methods=['GET'])
def generate_image_code(image_code_id):
    # 調用captcha擴展包
    name,text,image = captcha.generate_captcha()
    # 調用redis數據庫實例,存儲圖片驗證碼
    try:
        redis_store.setex('ImageCode_' + image_code_id,constants.IMAGE_CODE_REDIS_EXPIRES,text)
    except Exception as e:
        # 調用應用上下文,記錄項目錯誤日志信息
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR,errmsg='保存圖片驗證碼失敗')
    # 如果未發生異常,返回圖片本身
    else:
        # 使用響應對象,用來返回圖片
        response = make_response(image)
        # 設置響應報文的Content-Type = 'image/jpg'
        response.headers['Content-Type'] = 'image/jpg'
        # 返回響應response
        return response

 

發送短信

獲取參數–校驗參數–查詢數據–返回結果

 

 1. 獲取參數,圖片驗證碼和編號
 2. 校驗參數的完整性,mobile(手機號),text(圖片驗證碼),id(圖片驗證碼id)(參數全部存在,如少,則返回參數不完整,提醒輸入)
 3. 校驗mobile手機號格式,使用正則(如有錯誤,則返回手機格式不正確)
 4. 獲取本地存儲的真實圖片驗證碼
 5. 判斷獲取,圖片驗證碼是否存在過期(從redis數據庫不一定獲取得到,try一下)
 6. 刪除圖片驗證碼(因為圖片驗證碼只能使用一次)
 7. 比較圖片驗證碼(判斷客戶輸入與圖片生成是否一致,可以忽略大小寫)
 8. 生成短信內容,隨機數(短信驗證碼)
 9. 查詢數據庫,判斷手機號是否已經注冊(是否查詢到,try一下)
 10. 保存短信內容到redis中(生成短信驗證碼)
 11. 調用雲通訊發送短信
 12. 保存返回結果,判斷是否發送成功
 13. 返回結果
---------------------

實現代碼:

@api.route('/smscode/<mobile>',methods=['GET'])
def send_sms_code(mobile):
    # 獲取參數
    image_code = request.args.get('text')
    image_code_id = request.args.get('id')
    # 檢查參數的完整性,any--all
    if not all([mobile,image_code,image_code_id]):
        return jsonify(errno=RET.PARAMERR,errmsg='參數不完整')
    # 校驗手機號格式是否滿足
    if not re.match(r'1[3456789]\d{9}',mobile):
        return jsonify(errno=RET.PARAMERR,errmsg='手機號格式錯誤')
    # 檢查圖片驗證碼,獲取本地存儲的真實圖片驗證碼
    try:
        real_image_code = redis_store.get('ImageCode_' + image_code_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR,errmsg='查詢圖片驗證碼失敗')
    # 校驗獲取結果
    if not real_image_code:
        return jsonify(errno=RET.NODATA,errmsg='圖片驗證碼過期')
    # 刪除圖片驗證碼,圖片驗證碼只能操作一次
    try:
        redis_store.delete('ImageCode_' + image_code_id)
    except Exception as e:
        current_app.logger.error(e)
    # 比較圖片驗證碼是否一致,忽略大小寫
    if real_image_code.lower() != image_code.lower():
        return jsonify(errno=RET.DATAERR,errmsg='圖片驗證碼錯誤')
    # 查詢數據庫,判斷手機號是否已經注冊
    try:
        user = User.query.filter_by(mobile=mobile).first()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR,errmsg='查詢數據庫異常')
    else:
        # 判斷查詢結果
        if user:
            return jsonify(errno=RET.DATAEXIST,errmsg='手機號已注冊')
    # 構造短信隨機碼
    sms_code = '%06d' % random.randint(0,999999)
    # 保存短信隨機碼
    try:
        redis_store.setex('SMSCode_' + mobile,constants.SMS_CODE_REDIS_EXPIRES,sms_code)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR,errmsg='保存短信驗證碼失敗')
    # 調用雲通訊擴展,發送短信
    try:
        ccp = sms.CCP()
        # 調用雲通訊的模板方法發送短信
        result = ccp.send_template_sms(mobile,[sms_code,constants.SMS_CODE_REDIS_EXPIRES/60],1)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.THIRDERR,errmsg='發送短信異常')
    # 判斷result是否發送成功
    # result = 0
    if 0 == result:
        return jsonify(errno=RET.OK,errmsg='發送成功')
    else:
        return jsonify(errno=RET.THIRDERR,errmsg='發送失敗')

 

注冊用戶

1. 獲取參數,get_json()(獲取請求體參數手機號短信號密碼)
 2. 校驗參數存在
 3. 獲取詳細的參數,mobile,sms_code,password
 4. 校驗手機號格式
 5. 校驗短信驗證碼
 6. 獲取本地存儲的真實短信驗證碼
 7. 判斷查詢結果
 8. 比較短信驗證碼是否正確
 9. 刪除短信驗證碼(如果一致登入,並刪除比較后的驗證碼)
 10. 構建模型對象,准備保存用戶數據
    user = User(mobile=mobile,name=mobile)
    user.password = password
 11.使用數據庫會話對象提交到數據庫
 12.緩存用戶信息,到redis。session['user_id']=user_id
 13.返回結果,附屬信息data=user.to_dict()
--------------------- 

實現代碼:

@api.route('/users',methods=['POST'])
def register():
    # 獲取參數
    user_data = request.get_json()
    # 判斷獲取結果
    if not user_data:
        return jsonify(errno=RET.PARAMERR,errmsg='參數錯誤')
    # 獲取詳細的參數信息,mobile,sms_code,password
    # user_data['mobile']
    mobile = user_data.get('mobile')
    sms_code = user_data.get('sms_code')
    password = user_data.get('password')
    # 檢查參數的完整性
    if not all([mobile,sms_code,password]):
        return jsonify(errno=RET.PARAMERR,errmsg='參數缺失')
    # 手機號格式檢查
    if not re.match(r'1[3456789]\d{9}',mobile):
        return jsonify(errno=RET.PARAMERR,errmsg='手機號格式錯誤')
    # 判斷用戶是否已經注冊
    try:
        user = User.query.filter_by(mobile=mobile).first()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='查詢數據庫異常')
    else:
        # 判斷查詢結果
        if user:
            return jsonify(errno=RET.DATAEXIST, errmsg='手機號已注冊')
    # 獲取本地存儲的真實短信驗證碼
    try:
        real_sms_code = redis_store.get('SMSCode_' + mobile)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR,errmsg='查詢數據庫異常')
    # 判斷查詢redis的結果
    if not real_sms_code:
        return jsonify(errno=RET.NODATA,errmsg='短信驗證碼過期')
    # 直接比較短信驗證碼是否正確
    if real_sms_code != str(sms_code):
        return jsonify(errno=RET.DATAERR,errmsg='短信驗證碼錯誤')
    # 刪除短信驗證碼
    try:
        redis_store.delete('SMSCode_' + mobile)
    except Exception as e:
        current_app.logger.error(e)
    # 准備保存用戶注冊信息
    user = User(mobile=mobile,name=mobile)
    # 調用模型類中的方法generate_password_hash,對密碼進行加密sha256處理
    user.password = password
    # 提交數據到數據庫
    try:
        db.session.add(user)
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        # 如果提交數據發生異常,需要進行回滾
        db.session.rollback()
        return jsonify(errno=RET.DBERR,errmsg='保存用戶信息失敗')
    # 緩存用戶信息
    session['user_id'] = user.id
    session['mobile'] = mobile
    session['name'] = mobile
    # 返回結果
    return jsonify(errno=RET.OK,errmsg='OK',data=user.to_dict())

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM