搭建Tornado Https服務器之Tornado連接MySql數據庫(4-2增刪改查)

    在上一篇文章中我們已經準備好了兩張表users和classes,同時我們還在classes中插入了一條記錄,並且我們建了一個工程文件,那麼接下來在上一篇的基礎上,我們開始寫對users表的相關操作。

一、寫一個全局父類

       上一篇文章中我們提到,需要爲請求設置允許跨域,需要option函數,同時還發現連接函數也是共性,那麼爲了簡化代碼,我們不妨寫一個父類,包含這些方法,其他的請求類繼承此父類.

1、我們再handler目錄下新建basehandler.py文件,並在裏面寫下如下代碼:

import tornado.web # 導入tornado模塊

# 這是一個父類,此父類允許跨域,並對預請求做了處理
class BaseHandler(tornado.web.RequestHandler):
    """
    基本數據配置
    """
    # 連接數據庫參數,需要替換
    connect={
        'host' : 'x.x.x.x', 
        'port' : 3306, 
        'user' : 'root', 
        'passwd' : 'root', 
        'db' : 'test'
    }
    # 配置請求頭,允許跨域,否者在瀏覽器調用的時候報錯誤
    def set_default_headers(self):
        self.set_header("Access-Control-Allow-Origin", "*")
        self.set_header("Access-Control-Allow-Headers", "Content-Type")
        self.set_header("Access-Control-Allow-Methods", "POST,GET,OPTIONS")

    # 這個函數是必要的,有些瀏覽器或者測試工具在訪問之前都會預先訪問,你不寫的話會導致出錯的
    def options(self):
        self.finish()

2、下面我們更新classhandler.py文件代碼:

重點說明一下 **是解包的意思 可以將字典解開,把鍵值對一一取出

from basehandler import BaseHandler
import pymysql #導入連接mysql的驅動模塊

# 這是一個處理新建班級的請求類,繼承tornado.web.RequestHandler
class NewClassHandler(BaseHandler):
    # 重寫post請求函數,處理post請求
    def post(self):
        # 爲了防止出錯導致程序崩潰,我們需要捕獲異常函數,並處理 
        try:
            # 從請求中獲取參數,如果獲取不到,我們賦值 None
            classname = self.get_argument('classname', None)
            # 對傳入的參數進行判斷,如果爲空我們回覆 error,並終止執行下去
            if not classname:
                # self.write()函數的參數爲標準的json類型
                self.write({"error":"班級名稱爲空!"})
                return
            # 如果不爲空那麼開始訪問數據庫吧
            # 首先是sql語句
            sql = "insert into classes(classname) values('{0}')".format(classname)
            # 創建連接對象,相應的參數 意思依次爲 主機ip 端口 數據庫用戶名 數據庫用戶密碼 數據庫名稱
            # **是解包字典
            conn = pymysql.connect(**BaseHandler.connect)
            # 創建連接遊標,用於讀寫數據庫
            cursor = conn.cursor()
            # 執行sql語句,並返回影響行數
            effect_row = cursor.execute(sql)
            # 提交數據
            conn.commit()
            # 關閉遊標和連接
            cursor.close()
            conn.close()
            # 插入成功 那麼影響函數是1
            if effect_row>0:
                self.write({"success":"插入班級信息成功"})
            else:
                self.write({"error":"插入班級信息失敗"})
        except Exception as e:
            # 如果出現異常我們打印出來
            print(e)
            self.write({"error":"服務器出錯!"})

二、接下來就是寫userhandler.py文件了:

from basehandler import BaseHandler
import pymysql #導入連接mysql的驅動模塊

# 這是一個處理新建用戶的請求類,繼承BaseHandler
class NewUserHandler(BaseHandler):
    # 重寫post請求函數,處理post請求
    def post(self):
        # 爲了防止出錯導致程序崩潰,我們需要捕獲異常函數,並處理 
        try:
            # 從請求中獲取參數,如果獲取不到,我們賦值 None
            username = self.get_argument('username', None)
            password = self.get_argument('password', None)
            class_id = self.get_argument('class_id', None)
            # 對傳入的參數進行判斷,如果爲空我們回覆 error,並終止執行下去
            if not username:
                # self.write()函數的參數爲標準的json類型
                self.write({"error":"用戶賬號爲空!"})
                return
            if not password:
                # self.write()函數的參數爲標準的json類型
                self.write({"error":"用戶密碼爲空!"})
                return
            if not class_id:
                # self.write()函數的參數爲標準的json類型
                self.write({"error":"班級沒有選擇!"})
                return
            # 如果不爲空那麼開始訪問數據庫吧
            # 首先是sql語句
            sql = "insert into users(username,password,class_id) values('{0}','{1}',{2})".format(username,password,class_id)
            # 創建連接對象,相應的參數 意思依次爲 主機ip 端口 數據庫用戶名 數據庫用戶密碼 數據庫名稱
            conn = pymysql.connect(**BaseHandler.connect)
            # 創建連接遊標,用於讀寫數據庫
            cursor = conn.cursor()
            # 執行sql語句,並返回影響行數
            effect_row = cursor.execute(sql)
            # 提交數據
            conn.commit()
            # 關閉遊標和連接
            cursor.close()
            conn.close()
            # 插入成功 那麼影響函數是1
            if effect_row>0:
                self.write({"success":"插入用戶信息成功"})
            else:
                self.write({"error":"插入用戶信息失敗"})
        except Exception as e:
            # 如果出現異常我們打印出來
            print(e)
            self.write({"error":"服務器出錯!"})

# 這是一個處理獲取用戶信息的請求類,繼承BaseHandler
class GetUserHandler(BaseHandler):
    # 重寫get請求函數,處理get請求
    def get(self):
        # 爲了防止出錯導致程序崩潰,我們需要捕獲異常函數,並處理 
        try:
            # 從請求中獲取參數,如果獲取不到,我們賦值 None
            user_id = self.get_argument('id', None)
            # 對傳入的參數進行判斷,如果爲空我們回覆 error,並終止執行下去
            if not user_id:
                # self.write()函數的參數爲標準的json類型
                self.write({"error":"用戶id爲空!"})
                return
            # 如果不爲空那麼開始訪問數據庫吧
            # 首先是sql語句,我們獲取用戶信息當然希望獲取到班級信息啦,密碼也不需要啊,因此聯合查詢指定查詢字段走起
            # 被忘記指定字段屬主哦 不然 歧義報錯
            sql = "select users.id,username,users.createtime,classname from users join classes on classes.id=class_id where users.id={0}".format(user_id)
            # 創建連接對象
            conn = pymysql.connect(**BaseHandler.connect)
            # 創建連接遊標,用於讀寫數據庫
            cursor = conn.cursor()
            # 執行sql語句,並返回影響行數
            effect_row = cursor.execute(sql)
            # 通過遊標返回一行數據
            user = cursor.fetchone()
            # 關閉遊標和連接
            cursor.close()
            conn.close()
            # 返回的數據是元組,我們需要包裝一下
            user_dir={}
            if user:
                user_dir["id"]=user[0]
                user_dir["username"]=user[1]
                # createtime是timestamp類型,需要轉換成字符串型的
                user_dir["createtime"]=user[2].strftime('%Y-%m-%d %H:%M:%S')
                user_dir["classname"]=user[3]
            self.write({"success":user_dir})
        except Exception as e:
            # 如果出現異常我們打印出來
            print(e)
            self.write({"error":"服務器出錯!"})

# 這是一個處理獲取用戶列表的請求類,繼承BaseHandler
class ListUserHandler(BaseHandler):
    # 重寫get請求函數,處理get請求
    def get(self):
        # 爲了防止出錯導致程序崩潰,我們需要捕獲異常函數,並處理 
        try:
            # 首先是sql語句,我們獲取用戶信息當然希望獲取到班級信息啦,密碼也不需要啊,因此聯合查詢指定查詢字段走起
            # 被忘記指定字段屬主哦 不然 歧義報錯
            sql = "select users.id,username,users.createtime,classname from users join classes on classes.id=class_id"
            # 創建連接對象
            conn = pymysql.connect(**BaseHandler.connect)
            # 創建連接遊標,用於讀寫數據庫
            cursor = conn.cursor()
            # 執行sql語句,並返回影響行數
            effect_row = cursor.execute(sql)
            # 通過遊標返回一行數據
            users = cursor.fetchall()
            # 關閉遊標和連接
            cursor.close()
            conn.close()
            user_list=[]
            # 返回的數據是元組列表,我們需要包裝一下
            for user in users:
                user_dir={}
                user_dir["id"]=user[0]
                user_dir["username"]=user[1]
                # createtime是timestamp類型,需要轉換成字符串型的
                user_dir["createtime"]=user[2].strftime('%Y-%m-%d %H:%M:%S')
                user_dir["classname"]=user[3]
                user_list.append(user_dir)
            self.write({"success":user_list})
        except Exception as e:
            # 如果出現異常我們打印出來
            print(e)
            self.write({"error":"服務器出錯!"})

# 這是一個處理更改用戶信息的請求類,繼承BaseHandler
# 這裏我們只更改密碼,如果你有想法的可以自己增加
class UpdateUserHandler(BaseHandler):
    # 重寫post請求函數,處理post請求
    def post(self):
        # 爲了防止出錯導致程序崩潰,我們需要捕獲異常函數,並處理 
        try:
            # 從請求中獲取參數,如果獲取不到,我們賦值 None
            user_id = self.get_argument('id', None)
            password = self.get_argument('password', None)
            # 對傳入的參數進行判斷,如果爲空我們回覆 error,並終止執行下去
            if not user_id:
                # self.write()函數的參數爲標準的json類型
                self.write({"error":"用戶賬號爲空!"})
                return
            if not password:
                # self.write()函數的參數爲標準的json類型
                self.write({"error":"用戶密碼爲空!"})
                return
            # 如果不爲空那麼開始訪問數據庫吧
            # 首先是sql語句,因爲password是字符串類型 我們一般會加上單引號,防止報錯
            sql = "update users set password='{1}' where id={0}".format(user_id,password)
            # 創建連接對象
            conn = pymysql.connect(**BaseHandler.connect)
            # 創建連接遊標,用於讀寫數據庫
            cursor = conn.cursor()
            # 執行sql語句,並返回影響行數
            effect_row = cursor.execute(sql)
            # 提交數據
            conn.commit()
            # 關閉遊標和連接
            cursor.close()
            conn.close()
            # 需要注意的是,如果我們密碼沒有改變而更新的話,影響的行數其實是不變的
            if effect_row>0:
                self.write({"success":"更新用戶信息成功!"})
            else:
                self.write({"error":"更新用戶信息失敗!,可能前後更改數據一致。"})
        except Exception as e:
            # 如果出現異常我們打印出來
            print(e)
            self.write({"error":"服務器出錯!"})

# 這是一個處理刪除用戶信息的請求類,繼承BaseHandler
class DeleteUserHandler(BaseHandler):
    # 重寫get請求函數,處理get請求
    def get(self):
        # 爲了防止出錯導致程序崩潰,我們需要捕獲異常函數,並處理 
        try:
            # 從請求中獲取參數,如果獲取不到,我們賦值 None
            user_id = self.get_argument('id', None)
            # 對傳入的參數進行判斷,如果爲空我們回覆 error,並終止執行下去
            if not user_id:
                # self.write()函數的參數爲標準的json類型
                self.write({"error":"用戶賬號爲空!"})
                return
            # 如果不爲空那麼開始訪問數據庫吧
            sql = "delete from users where id={0}".format(user_id)
            # 創建連接對象
            conn = pymysql.connect(**BaseHandler.connect)
            # 創建連接遊標,用於讀寫數據庫
            cursor = conn.cursor()
            # 執行sql語句,並返回影響行數
            effect_row = cursor.execute(sql)
            # 提交數據
            conn.commit()
            # 關閉遊標和連接
            cursor.close()
            conn.close()
            # 需要注意的是,如果我們密碼沒有改變而更新的話,影響的行數其實是不變的
            if effect_row>0:
                self.write({"success":"刪除用戶信息成功!"})
            else:
                self.write({"error":"刪除用戶信息失敗!"})
        except Exception as e:
            # 如果出現異常我們打印出來
            print(e)
            self.write({"error":"服務器出錯!"})

需要更新main.py文件,添加更多的路由

import sys
# 將handler目錄下的文件放到和main.py文件同級目錄下,便於我們引用
sys.path.append("./handler")
# 添加必要的tornado的模塊
import tornado.ioloop
import tornado.web
# 從classhandler.py文件中導出寫好的 類
from classhandler import NewClassHandler
from userhandler import NewUserHandler,GetUserHandler,ListUserHandler,UpdateUserHandler,DeleteUserHandler

# 寫程序入口函數 main函數
def main():
    # 定義請求的路徑和響應的請求類,此類會根據你發出的請求區分get 還是post而給予不同的處理
    application = tornado.web.Application([
        (r"/class/new", NewClassHandler),
        (r"/user/new", NewUserHandler),
        (r"/user/info", GetUserHandler),
        (r"/user/list", ListUserHandler),
        (r"/user/update", UpdateUserHandler),
        (r"/user/delete", DeleteUserHandler),
        ])
    # 綁定端口,單進程啓動
    application.listen(8000)
    tornado.ioloop.IOLoop.instance().start()

if __name__ == "__main__":
    main()

三、接下來我們測試一下

執行main.py文件

1、插入用戶,我們插入兩個,因爲刪除和獲取列表需要

2、根據id更改用戶密碼

3、根據id查看用戶信息 

4、獲取用戶列表

 

 

5、刪除用戶

 

我們看一下數據庫

到此我們已經結束對mysql的簡單學習,下一章我們將要嘗試連接postgresql數據庫。 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章