鍍金池/ 教程/ Python/ 用 tornado 做網(wǎng)站 (3)
標(biāo)準(zhǔn)庫(kù) (4)
如何成為 Python 高手
標(biāo)準(zhǔn)庫(kù) (6)
標(biāo)準(zhǔn)庫(kù) (3)
類(2)
Pandas 使用 (2)
xml
用 tornado 做網(wǎng)站 (5)
文件(1)
練習(xí)
列表(3)
從小工到專家
除法
錯(cuò)誤和異常 (2)
函數(shù)(1)
用 tornado 做網(wǎng)站 (7)
為做網(wǎng)站而準(zhǔn)備
函數(shù)練習(xí)
標(biāo)準(zhǔn)庫(kù) (8)
Pandas 使用 (1)
回顧 list 和 str
字典(1)
用 tornado 做網(wǎng)站 (3)
字符串(1)
函數(shù)(2)
寫一個(gè)簡(jiǎn)單的程序
將數(shù)據(jù)存入文件
語(yǔ)句(5)
SQLite 數(shù)據(jù)庫(kù)
集成開(kāi)發(fā)環(huán)境(IDE)
集合(1)
類(1)
用 tornado 做網(wǎng)站 (6)
用 tornado 做網(wǎng)站 (2)
自省
語(yǔ)句(4)
錯(cuò)誤和異常 (1)
用 tornado 做網(wǎng)站 (4)
集合(2)
列表(1)
標(biāo)準(zhǔn)庫(kù) (1)
生成器
mysql 數(shù)據(jù)庫(kù) (1)
第三方庫(kù)
實(shí)戰(zhàn)
運(yùn)算符
類(3)
字典(2)
語(yǔ)句(1)
數(shù)和四則運(yùn)算
語(yǔ)句(2)
文件(2)
MySQL 數(shù)據(jù)庫(kù) (2)
電子表格
迭代器
mongodb 數(shù)據(jù)庫(kù) (1)
特殊方法 (2)
特殊方法 (1)
字符編碼
編寫模塊
用 tornado 做網(wǎng)站 (1)
標(biāo)準(zhǔn)庫(kù) (5)
函數(shù)(4)
類(5)
字符串(2)
關(guān)于 Python 的故事
函數(shù)(3)
字符串(4)
處理股票數(shù)據(jù)
常用數(shù)學(xué)函數(shù)和運(yùn)算優(yōu)先級(jí)
字符串(3)
為計(jì)算做準(zhǔn)備
多態(tài)和封裝
類(4)
迭代
語(yǔ)句(3)
錯(cuò)誤和異常 (3)
分析 Hello
Python 安裝
標(biāo)準(zhǔn)庫(kù) (2)
列表(2)
元組

用 tornado 做網(wǎng)站 (3)

數(shù)據(jù)傳輸

在已經(jīng)建立了前端表單之后,就要實(shí)現(xiàn)前端和后端之間的數(shù)據(jù)傳遞。在工程中,常用到一個(gè)被稱之為 ajax() 的方法。

關(guān)于 ajax 的故事,需要濃墨重彩,因?yàn)樗銐蚓省?/p>

ajax 是“Asynchronous Javascript and XML”(異步 JavaScript 和 XML)的縮寫,在它的發(fā)展歷程中,匯集了眾家貢獻(xiàn)。比如微軟的 IE 團(tuán)隊(duì)曾經(jīng)將 XHR(XML HttpRequest) 用于 web 瀏覽器和 web 服務(wù)器間傳輸數(shù)據(jù),并且被 W3C 標(biāo)準(zhǔn)采用。當(dāng)然,也有其它公司為 Ajax 技術(shù)做出了貢獻(xiàn),雖然它們都被遺忘了,比如 Oddpost,后來(lái)被 Yahoo!收購(gòu)并成為 Yahoo! Mail 的基礎(chǔ)。但是,真正讓 Ajax 大放異彩的 google 是不能被忽視的,正是 google 在 Gmail、Suggest 和 Maps 上大規(guī)模使用了 Ajax,才使得人們看到了它的魅力,程序員由此而興奮。

技術(shù)總是在不斷進(jìn)化的,進(jìn)化的方向就是用著越來(lái)越方便。

回到上一節(jié)使用的 jQuery,里面就有 ajax() 方法,能夠讓程序員方便的調(diào)用。

ajax() 方法通過(guò) HTTP 請(qǐng)求加載遠(yuǎn)程數(shù)據(jù)。

該方法是 jQuery 底層 AJAX 實(shí)現(xiàn)。簡(jiǎn)單易用的高層實(shí)現(xiàn)見(jiàn) $.get, $.post 等。$.ajax() 返回其創(chuàng)建的 XMLHttpRequest 對(duì)象。大多數(shù)情況下你無(wú)需直接操作該函數(shù),除非你需要操作不常用的選項(xiàng),以獲得更多的靈活性。

最簡(jiǎn)單的情況下,$.ajax() 可以不帶任何參數(shù)直接使用。

在上文介紹 Ajax 的時(shí)候,用到了一個(gè)重要的術(shù)語(yǔ)——“異步”,與之相對(duì)應(yīng)的叫做“同步”。我引用來(lái)自阮一峰的網(wǎng)絡(luò)日志中的通俗描述:

"同步模式"就是上一段的模式,后一個(gè)任務(wù)等待前一個(gè)任務(wù)結(jié)束,然后再執(zhí)行,程序的執(zhí)行順序與任務(wù)的排列順序是一致的、同步的;"異步模式"則完全不同,每一個(gè)任務(wù)有一個(gè)或多個(gè)回調(diào)函數(shù)(callback),前一個(gè)任務(wù)結(jié)束后,不是執(zhí)行后一個(gè)任務(wù),而是執(zhí)行回調(diào)函數(shù),后一個(gè)任務(wù)則是不等前一個(gè)任務(wù)結(jié)束就執(zhí)行,所以程序的執(zhí)行順序與任務(wù)的排列順序是不一致的、異步的。

"異步模式"非常重要。在瀏覽器端,耗時(shí)很長(zhǎng)的操作都應(yīng)該異步執(zhí)行,避免瀏覽器失去響應(yīng),最好的例子就是 Ajax 操作。在服務(wù)器端,"異步模式"甚至是唯一的模式,因?yàn)閳?zhí)行環(huán)境是單線程的,如果允許同步執(zhí)行所有 http 請(qǐng)求,服務(wù)器性能會(huì)急劇下降,很快就會(huì)失去響應(yīng)。

看來(lái),ajax() 是前后端進(jìn)行數(shù)據(jù)傳輸?shù)闹匾巧?/p>

承接上一節(jié)的內(nèi)容,要是用 ajax() 方法,需要修改 script.js 文件內(nèi)容即可:

$(document).ready(function(){
    $("#login").click(function(){
        var user = $("#username").val();
        var pwd = $("#password").val();
        var pd = {"username":user, "password":pwd};
        $.ajax({
            type:"post",
            url:"/",
            data:pd,
            cache:false,
            success:function(data){
                alert(data);
            },
            error:function(){
                alert("error!");
            },
        });
    });
});

在這段代碼中,var pd = {"username":user, "password":pwd};意即將得到的 user 和 pwd 值,放到一個(gè) json 對(duì)象中(關(guān)于 json,請(qǐng)閱讀《標(biāo)準(zhǔn)庫(kù)(8)》),形成了一個(gè) json 對(duì)象。接下來(lái)就是利用 ajax() 方法將這個(gè) json 對(duì)象傳給后端。

jQuery 中的 ajax() 方法使用比較簡(jiǎn)單,正如上面代碼所示,只需要 $.ajax() 即可,不過(guò)需要對(duì)立面的參數(shù)進(jìn)行說(shuō)明。

  • type:post 還是 get。關(guān)于 post 和 get 的區(qū)別,可以閱讀:HTTP POST GET 本質(zhì)區(qū)別詳解
  • url:post 或者 get 的地址
  • data:傳輸?shù)臄?shù)據(jù),包括三種:(1)html 拼接的字符串;(2)json 數(shù)據(jù);(3)form 表單經(jīng) serialize() 序列化的。本例中傳輸?shù)木褪?json 數(shù)據(jù),這也是經(jīng)常用到的一種方式。
  • cache:默認(rèn)為 true,如果不允許緩存,設(shè)置為 false.
  • success:請(qǐng)求成功時(shí)執(zhí)行回調(diào)函數(shù)。本例中,將返回的 data 用 alert 方式彈出來(lái)。讀者是否注意到,我在很多地方都用了 alert() 這個(gè)東西,目的在于調(diào)試,走一步看一步,看看得到的數(shù)據(jù)是否如自己所要。也是有點(diǎn)不自信呀。
  • error:如果請(qǐng)求失敗所執(zhí)行的函數(shù)。

后端接受數(shù)據(jù)

前端通過(guò) ajax 技術(shù),將數(shù)據(jù)已 json 格式傳給了后端,并且指明了對(duì)象目錄"/",這個(gè)目錄在 url.py 文件中已經(jīng)做了配置,是由 handlers 目錄的 index.py 文件的 IndexHandler 類來(lái)出來(lái)。因?yàn)槭怯?post 方法傳的數(shù)據(jù),那么在這個(gè)類中就要有 post 方法來(lái)接收數(shù)據(jù)。所以,要在 IndexHandler 類中增加 post(),增加之后的完善代碼是:

#!/usr/bin/env Python
# coding=utf-8

import tornado.web

class IndexHandler(tornado.web.RequestHandler):
    def get(self):
        self.render("index.html")

    def post(self):
        username = self.get_argument("username")
        password = self.get_argument("password")
        self.write(username)

在 post() 方法中,使用 get_argument() 函數(shù)來(lái)接收前端傳過(guò)來(lái)的數(shù)據(jù),這個(gè)函數(shù)的完整格式是 get_argument(name, default=[], strip=True),它能夠獲取 name 的值。在上面的代碼中,name 就是從前端傳到后端的那個(gè) json 對(duì)象的鍵的名字,是哪個(gè)鍵就獲取該鍵的值。如果獲取不到 name 的值,就返回 default 的值,但是這個(gè)值默認(rèn)是沒(méi)有的,如果真的沒(méi)有就會(huì)拋出 HTTP 400。特別注意,在 get 的時(shí)候,通過(guò) get_argument() 函數(shù)獲得 url 的參數(shù),如果是多個(gè)參數(shù),就獲取最后一個(gè)的值。要想獲取多個(gè)值,可以使用 get_arguments(name, strip=true)

上例中分別用 get_argument() 方法得到了 username 和 password,并且它們都是 unicode 編碼的數(shù)據(jù)。

tornado.web.RequestHandler 的方法 write(),即上例中的 self.write(username),是后端向前端返回?cái)?shù)據(jù)。這里返回的實(shí)際上是一個(gè)字符串,也可返回 json 字符串。

如果讀者要查看修改代碼之后的網(wǎng)站效果,最有效的方式先停止網(wǎng)站(ctrl+c),在從新執(zhí)行 Python server.py 運(yùn)行網(wǎng)站,然后刷新瀏覽器即可。這是一種較為笨拙的方法。一種靈巧的方法是開(kāi)啟調(diào)試模式。是否還記得?在設(shè)置 setting 的時(shí)候,寫上 debug = True 就表示是調(diào)試模式了(參閱:用 tornado 做網(wǎng)站 (1))。但是,調(diào)試模式也不是十全十美,如果修改模板,就不會(huì)加載,還需要重啟服務(wù)。反正重啟也不麻煩,無(wú)妨啦。

看看上面的代碼效果:

http://wiki.jikexueyuan.com/project/start-learning-python/images/30501.png" alt="" />

這是前端輸入了用戶名和密碼之后,點(diǎn)擊 login 按鈕,提交給后端,后端再向前端返回?cái)?shù)據(jù)之后的效果。就是我們想要的結(jié)果。

驗(yàn)證用戶名和密碼

按照流程,用戶在前端輸入了用戶名和密碼,并通過(guò) ajax 提交到了后端,后端借助于 get_argument() 方法得到了所提交的數(shù)據(jù)(用戶名和密碼)。下面要做的事情就是驗(yàn)證這個(gè)用戶名和密碼是否合法,其體現(xiàn)在:

  • 數(shù)據(jù)庫(kù)中是否有這個(gè)用戶
  • 密碼和用戶先前設(shè)定的密碼(已經(jīng)保存在數(shù)據(jù)庫(kù)中)是否匹配

這個(gè)驗(yàn)證工作完成之后,才能允許用戶登錄,登錄之后才能繼續(xù)做某些事情。

首先,在 methods 目錄中(已經(jīng)有了一個(gè) db.py)創(chuàng)建一個(gè)文件,我命名為 readdb.py,專門用來(lái)存儲(chǔ)讀數(shù)據(jù)用的函數(shù)(這種劃分完全是為了明確和演示一些應(yīng)用方法,讀者也可以都寫到 db.py 中)。這個(gè)文件的代碼如下:

#!/usr/bin/env Python
# coding=utf-8

from db import *

def select_table(table, column, condition, value ):
    sql = "select " + column + " from " + table + " where " + condition + "='" + value + "'"
    cur.execute(sql)
    lines = cur.fetchall()
    return lines

上面這段代碼,建議讀者可以寫上注釋,以檢驗(yàn)自己是否能夠?qū)⒁酝闹R(shí)融會(huì)貫通地應(yīng)用。恕我不再解釋。

有了這段代碼之后,就進(jìn)一步改寫 index.py 中的 post() 方法。為了明了,將 index.py 的全部代碼呈現(xiàn)如下:

#!/usr/bin/env Python
# coding=utf-8

import tornado.web
import methods.readdb as mrd

class IndexHandler(tornado.web.RequestHandler):
    def get(self):
        self.render("index.html")

    def post(self):
        username = self.get_argument("username")
        password = self.get_argument("password")
        user_infos = mrd.select_table(table="users",column="*",condition="username",value=username)
        if user_infos:
            db_pwd = user_infos[0][2]
            if db_pwd == password:
                self.write("welcome you: " + username)
            else:
                self.write("your password was not right.")
        else:
            self.write("There is no thi user.")

特別注意,在 methods 目錄中,不要缺少了__init__.py文件,才能在 index.py 中實(shí)現(xiàn) import methods.readdb as mrd

代碼修改到這里,看到的結(jié)果是:

http://wiki.jikexueyuan.com/project/start-learning-python/images/30502.png" alt="" />

這是正確輸入用戶名(所謂正確,就是輸入的用戶名和密碼合法,即在數(shù)據(jù)庫(kù)中有該用戶名,且密碼匹配),并提交數(shù)據(jù)后,反饋給前端的歡迎信息。

http://wiki.jikexueyuan.com/project/start-learning-python/images/30503.png" alt="" />

如果輸入的密碼錯(cuò)誤了,則如此提示。

http://wiki.jikexueyuan.com/project/start-learning-python/images/30504.png" alt="" />

這是隨意輸入的結(jié)果,數(shù)據(jù)庫(kù)中無(wú)此用戶。

需要特別說(shuō)明一點(diǎn),上述演示中,數(shù)據(jù)庫(kù)中的用戶密碼并沒(méi)有加密。關(guān)于密碼加密問(wèn)題,后續(xù)要研究。


總目錄   |   上節(jié):用 tornado 做網(wǎng)站 (2)   |   下節(jié):用 tornado 做網(wǎng)站 (4)

如果你認(rèn)為有必要打賞我,請(qǐng)通過(guò)支付寶:qiwsir@126.com,不勝感激。