python:python bottle實現jquery ajax調取資料藉口
阿新 • • 發佈:2018-12-09
開發環境:
- python 3.6+
- python bottle 0.13
需求
後臺路由框架與ajax的配合不友好,大概是通病,雖然bottle 已經提供了非常強大的請求處理方法,但是都基於頁面重載入,在某些場景,其實並不需要重載入頁面,只是需要向後端傳送請求,得到請求已經接收的響應即可。如下圖所示場景:
在註冊過程中,通過所輸入郵箱,點選獲取驗證碼,只需向後端傳送請求,讓後端傳送郵件到輸入郵箱,根本不需要重新整理當前頁面。要實現無重新整理,jquery ajax是一個比較好的方法之一。
實現原理
註冊頁面html程式碼
<form action="/sign_do" method="post">
<div class="form-group login_header">
<div class="row">
<div class="col-sm-4">
<span><strong>註冊</strong></span>
</div>
<div class="col-sm-8 go_sign">
<a href="/login">已有賬號?去登入>></a>
</div>
</div>
</div>
<div class="form-group">
<label for="InputEmail1">Email address</label>
<input type="email" class="form-control" id="InputEmail1" placeholder="Email" name="username" value="{{username}}">
</div>
<div class="form-group">
<label for="InputVerification">驗證碼</label>
<div class="row">
<div class="col-md-7">
<input type="text" class="form-control" id="InputVerification" placeholder="ver_code" name="ver_code">
</div>
<div class="col-md-5">
<button type="button" class="btn btn-default btn_ver_code">獲取驗證碼</button>
</div>
</div>
</div>
<div class="form-group">
<label for="InputPassword1">Password</label>
<input type="password" class="form-control" id="InputPassword1" placeholder="Password" name="password1">
</div>
<div class="form-group">
<label for="InputPassword2">Password</label>
<input type="password" class="form-control" id="InputPassword2" placeholder="Password" name="password2">
<p class="help-block warning">{{message}}</p>
<p class="help-block error"></p>
</div>
<button type="submit" class="btn btn_do">確定</button>
</form>
傳送ajax請求js程式碼
<script>
$(".btn_ver_code").bind("click", function(ev){
var username = $("#InputEmail1").val();
$(".help-block.warning").hide();
if($.trim(username) == ''){
$(".help-block.error").text("郵箱不能為空!");
return false;
}
$(".help-block.error").text("請求已傳送,請耐心等待郵件傳送提示。");
$.ajax({
type: 'POST',
url: '/sign/get_ver_code',
data: {_method: 'get', _form: username},
dataType: 'json',
success: function (data){
$(".help-block.error").text(data.get_ver_code_state);
},
error: function () {
}
});
});
</script>
這樣,獲取的驗證碼的請求就到傳送到後臺了,但是bottle route是無法直接接受ajax請求的,這時候需要在後臺全域性方法裡註冊一個請求,用來捕捉ajax,也就是hook(鉤子),程式碼如下
@hook('before_request')
def validate():
"""使用勾子處理頁面或介面訪問事件"""
if request.method == 'POST' and request.POST.get('_method'):
request.environ['REQUEST_METHOD'] = request.POST.get('_method', '').upper()
if request.POST.get('_form'):
request.environ['REQUEST_FORM'] = request.POST.get('_form', '')
這段程式碼會攔截所有 ajax 請求,其中 ajax 傳送方式 “POST” 和傳入引數 “_method” 在這裡作為正確請求的標記,當請求正確驗證後,將傳送的資料 “_form” 存入 request.environ[‘REQUEST_FORM’], 其中 REQUEST_FORM 是一個自定義引數。
這一步只是捕捉到了請求,並且捕捉到了請求的所攜帶的資料,還需要一個執行請求的方法,去執行真正 ajax 的 /sign/get_ver_code 方法,程式碼如下:
@get('/sign/get_ver_code')
def sign():
username = request.environ['REQUEST_FORM']
sql = """
SELECT * FROM user WHERE username=%s
"""
res = Do_sql.readdb(sql, (username, ))
if not res:
ver_code = Do_common.create_ver_code()
apply_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
sql = """
SELECT * FROM user_sign WHERE username=%s
"""
res = Do_sql.readdb(sql, (username,))
if len(res) > 0:
res = res[0]
apply_s = int(time.mktime(time.strptime(str(res['apply_time']), "%Y-%m-%d %H:%M:%S")))
active_s = int(time.mktime(time.strptime(apply_time, "%Y-%m-%d %H:%M:%S")))
if res['apply_res'] == 0 and active_s - apply_s < 3600:
return {"get_ver_code_state": "操作過於頻繁,上一個驗證碼仍有效。"}
msg = "註冊驗證碼,請查收".encode('utf-8')
msg_text = "\n你有兩次嘗試機會,兩次輸錯驗證碼,則驗證碼失效。"
variable = Do_common.mail_do(username, ver_code, msg, msg_text)
try:
smtpObj = smtplib.SMTP()
smtpObj.connect(variable['mail_host'], 25) # 25 為 SMTP 埠號
smtpObj.login(variable['mail_user'], variable['mail_pass'])
smtpObj.sendmail(variable['mail_user'], variable['receivers'], variable['message'].as_string())
sql = """
INSERT INTO user_sign (username, ver_code, apply_time) VALUES (%s, %s, %s)
"""
res = Do_sql.writedb(sql, (username, ver_code, apply_time))
if res:
return {"get_ver_code_state": "驗證碼已傳送,可能被當成垃圾郵件。"}
else:
return {"get_ver_code_state": "未知錯誤,郵件傳送錯誤,請重試。"}
except smtplib.SMTPException:
return {"get_ver_code_state": "未知錯誤,郵件傳送錯誤,請重試。"}
else:
return {"get_ver_code_state": "郵箱已被註冊,請更換郵箱。"}
@get 是 bottle 的方法from bottle import hook, get, put
,這裡可以換成 @put。 當該方法開始執行,會根據各種條件,返回最終狀態。前端就可以無重新整理接收,在前端 <p class="help-block error"></p>
這裡顯示