使用Flask開發簡單接口(3)--引入MySQL

前言

前面的兩篇文章中,咱們已經學習了經過Flask開發GET和POST請求接口,但一直沒有實現操做數據庫,那麼咱們今天的目的,就是學習如何將MySQL數據庫運用到當前的接口項目中。html

本人環境:Python 3.7.0MySQL 5.7python

Flask操做MySQL的2種方式

通常狀況,Flask操做MySQL比較常見的方式有2種:SQLAlchemy操做SQL操做 。經過SQLAlchemy操做時,由於大可能是經過數據庫對象來操做,因此不須要寫多少SQL語句,但爲了順便鞏固一下SQL知識,在本文章中,咱們將採用SQL操做來進行學習。mysql

目前網上的相關文章中,大多數介紹的都是SQLAlchemy操做,SQLAlchemy操做相對也更簡單好用一些,由於SQLAlchemy爲Python與SQL之間創建了映射,若是使用它能夠極大減小SQL語句的編寫。git

在使用SQL操做方式時,咱們須要知道如何利用Python操做MySQL數據庫,若是不太清楚的話,能夠參考我以前的一篇文章:利用Python操做MySQL數據庫github

數據庫設計

咱們建立一個數據庫,命名爲 flask_demo ,而後新建一個數據表 user ,建表語句以下:sql

CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(20) NOT NULL,
  `password` varchar(255) NOT NULL,
  `role` tinyint(1) NOT NULL,
  `sex` tinyint(1) DEFAULT NULL,
  `telephone` varchar(255) NOT NULL,
  `address` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `telephone` (`telephone`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

user表中各字段對應含義以下:數據庫

id:用戶id號,自增加
username:用戶名
password:密碼
role:用戶角色,0表示管理員用戶,1表示普通用戶
sex:性別,0表示男性,1表示女性,容許爲空
telephone:手機號
address:聯繫地址,容許爲空

user表建立完成後,經過 DESC user 來查看下錶結構。json

mysql> DESC user;
+-----------+--------------+------+-----+---------+----------------+
| Field     | Type         | Null | Key | Default | Extra          |
+-----------+--------------+------+-----+---------+----------------+
| id        | int(11)      | NO   | PRI | NULL    | auto_increment |
| username  | varchar(20)  | NO   |     | NULL    |                |
| password  | varchar(255) | NO   |     | NULL    |                |
| role      | tinyint(1)   | NO   |     | NULL    |                |
| sex       | tinyint(1)   | YES  |     | NULL    |                |
| telephone | varchar(255) | NO   | UNI | NULL    |                |
| address   | varchar(255) | YES  |     | NULL    |                |
+-----------+--------------+------+-----+---------+----------------+
7 rows in set (0.00 sec)

新增配置文件

咱們在項目根路徑下新建一個包 config ,在該包下存放配置文件 setting.py ,該文件用於配置 MySQL 的服務器地址、端口、用戶名及密碼、數據庫名等參數。flask

# 服務端口配置
SERVER_PORT = 9999

# MySQL配置
MYSQL_HOST = "192.168.89.128"
MYSQL_PORT = 3306
MYSQL_USER = "root"
MYSQL_PASSWD = "123456"
MYSQL_DB = "flask_demo"

Python操做MySQL

咱們在項目根路徑下新建一個包 common ,在該包下新建文件 mysql_operate.py ,該文件下封裝了Python操做MySQL的代碼,後續將經過調用該文件的 db 對象及方法來操做數據庫。api

import pymysql
from config.setting import MYSQL_HOST,MYSQL_PORT,MYSQL_USER,MYSQL_PASSWD,MYSQL_DB

class MysqlDb():

    def __init__(self, host, port, user, passwd, db):
        # 創建數據庫鏈接
        self.conn = pymysql.connect(
            host=host,
            port=port,
            user=user,
            passwd=passwd,
            db=db
        )
        # 經過 cursor() 建立遊標對象,並讓查詢結果以字典格式輸出
        self.cur = self.conn.cursor(cursor=pymysql.cursors.DictCursor)

    def __del__(self): # 對象資源被釋放時觸發,在對象即將被刪除時的最後操做
        # 關閉遊標
        self.cur.close()
        # 關閉數據庫鏈接
        self.conn.close()

    def select_db(self, sql):
        """查詢"""
        # 檢查鏈接是否斷開,若是斷開就進行重連
        self.conn.ping(reconnect=True)
        # 使用 execute() 執行sql
        self.cur.execute(sql)
        # 使用 fetchall() 獲取查詢結果
        data = self.cur.fetchall()
        return data

    def execute_db(self, sql):
        """更新/新增/刪除"""
        try:
            # 檢查鏈接是否斷開,若是斷開就進行重連
            self.conn.ping(reconnect=True)
            # 使用 execute() 執行sql
            self.cur.execute(sql)
            # 提交事務
            self.conn.commit()
        except Exception as e:
            print("操做出現錯誤:{}".format(e))
            # 回滾全部更改
            self.conn.rollback()

db = MysqlDb(MYSQL_HOST, MYSQL_PORT, MYSQL_USER, MYSQL_PASSWD, MYSQL_DB)

完善GET和POST請求接口

  • 獲取全部用戶信息(GET接口)
@app.route("/users", methods=["GET"])
def get_all_users():
    """獲取全部用戶信息"""
    sql = "SELECT * FROM user"
    data = db.select_db(sql)
    print("獲取全部用戶信息 == >> {}".format(data))
    return jsonify({"code": "0", "data": data, "msg": "查詢成功"})
  • 獲取某個用戶信息(GET接口)
@app.route("/users/<string:username>", methods=["GET"])
def get_user(username):
    """獲取某個用戶信息"""
    sql = "SELECT * FROM user WHERE username = '{}'".format(username)
    data = db.select_db(sql)
    print("獲取 {} 用戶信息 == >> {}".format(username, data))
    if data:
        return jsonify({"code": "0", "data": data, "msg": "查詢成功"})
    return jsonify({"code": "1004", "msg": "查不到相關用戶的信息"})
  • 用戶註冊接口(POST接口)
@app.route("/register", methods=['POST'])
def user_register():
    """用戶註冊"""
    username = request.json.get("username").strip()  # 用戶名
    password = request.json.get("password").strip()  # 密碼
    sex = request.json.get("sex", "0").strip()  # 性別,默認爲0(男性)
    telephone = request.json.get("telephone", "").strip()  # 手機號,默認爲空串
    address = request.json.get("address", "").strip()  # 地址,默認爲空串
    if username and password and telephone:
        sql1 = "SELECT username FROM user WHERE username = '{}'".format(username)
        res1 = db.select_db(sql1)
        print("查詢到用戶名 ==>> {}".format(res1))
        sql2 = "SELECT telephone FROM user WHERE telephone = '{}'".format(telephone)
        res2 = db.select_db(sql2)
        print("查詢到手機號 ==>> {}".format(res2))
        if res1:
            return jsonify({"code": 2002, "msg": "用戶名已存在,註冊失敗!!!"})
        elif not (sex == "0" or sex == "1"):
            return jsonify({"code": 2003, "msg": "輸入的性別只能是 0(男) 或 1(女)!!!"})
        elif not (len(telephone) == 11 and re.match("^1[3,5,7,8]\d{9}$", telephone)):
            return jsonify({"code": 2004, "msg": "手機號格式不正確!!!"})
        elif res2:
            return jsonify({"code": 2005, "msg": "手機號已被註冊!!!"})
        else:
            sql3 = "INSERT INTO user(username, password, role, sex, telephone, address) " \
                  "VALUES('{}', '{}', '1', '{}', '{}', '{}')".format(username, password, sex, telephone, address)
            db.execute_db(sql3)
            print("新增用戶信息 ==>> {}".format(sql3))
            return jsonify({"code": 0, "msg": "恭喜,註冊成功!"})
    else:
        return jsonify({"code": 2001, "msg": "用戶名/密碼/手機號不能爲空,請檢查!!!"})

在這裏,咱們實現用戶註冊的時候,設置只能註冊 role 字段值爲 1 的普通用戶,不容許直接註冊管理員用戶。相關的接口返回碼和請求場景以下:

接口返回碼 請求場景
0 請求參數正確,註冊成功
2001 請求參數中,用戶名/密碼/手機號,任一參數爲空
2002 請求參數中,用戶名已被其餘人註冊使用
2003 請求參數中, sex 性別字段值不是 0 或 1
2004 請求參數中,手機號格式不正確
2005 請求參數中,手機號已被其餘人註冊使用

可參考以下進行用戶註冊接口請求:

請求方式:POST
請求地址:http://127.0.0.1:5000/register
請求頭:
Content-Type: application/json

Body:{"username": "wintest5", "password": "123456", "sex": "1", "telephone":"13500010005", "address": "上海市黃浦區"}

接口請求示例

  • 用戶登陸接口(POST接口)
@app.route("/login", methods=['POST'])
def user_login():
    """用戶登陸"""
    username = request.values.get("username").strip()
    password = request.values.get("password").strip()
    if username and password:
        sql1 = "SELECT username FROM user WHERE username = '{}'".format(username)
        res1 = db.select_db(sql1)
        print("查詢到用戶名 ==>> {}".format(res1))
        if not res1:
            return jsonify({"code": 1003, "msg": "用戶名不存在!!!"})
        sql2 = "SELECT * FROM user WHERE username = '{}' and password = '{}'".format(username, password)
        res2 = db.select_db(sql2)
        print("獲取 {} 用戶信息 == >> {}".format(username, res2))
        if res2:
            return jsonify({"code": 0, "msg": "恭喜,登陸成功!"})
        return jsonify({"code": 1002, "msg": "用戶名或密碼錯誤!!!"})
    else:
        return jsonify({"code": 1001, "msg": "用戶名或密碼不能爲空!!!"})

相關的接口返回碼和請求場景以下:

接口返回碼 請求場景
0 用戶名和密碼正確,登陸成功
1001 請求參數中,用戶名或密碼爲空
1002 請求參數中,用戶名正確,密碼錯誤
1003 請求參數中,使用了未註冊的用戶名

可參考以下進行用戶登陸接口請求:

請求方式:POST
請求地址:http://127.0.0.1:5000/login
請求頭:
Content-Type: application/x-www-form-urlencoded

Body:username=wintest&password=123456

接口請求示例

將項目在服務器部署

  • app.run() 啓動應用時配置參數

在Flask中,咱們經過 app.run() 啓動應用時,能夠配置一些參數,好比能夠配置以下:

from config.setting import SERVER_PORT
if __name__ == '__main__':
    # host爲主機ip地址,port指定訪問端口號,debug=True設置調試模式打開
    app.run(host="0.0.0.0", port=SERVER_PORT, debug=True)

上面代碼中,host需設置爲 0.0.0.0,這樣才能在外網進行訪問,好比咱們在Linux下部署項目,若是想在Windows中進行請求訪問,那麼就須要設置爲 0.0.0.0

  • 將項目根路徑加入環境變量

咱們把項目根路徑下的 app.py 當作該項目的應用啓動入口文件,那麼就須要將項目的根路徑臨時加入到環境變量中,不然啓動應用時可能會提示找不到相關模塊,具體配置以下:

import os, sys
from config.setting import SERVER_PORT
from api.user import app

# 項目根路徑
BASE_PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.insert(0, BASE_PATH)  # 將項目根路徑臨時加入環境變量,程序退出後失效

if __name__ == '__main__':
    # host爲主機ip地址,port指定訪問端口號,debug=True設置調試模式打開
    app.run(host="0.0.0.0", port=SERVER_PORT, debug=True)
  • 命令行啓動應用

咱們這個項目的啓動,只須要一行命令就能夠搞定,以Linux下後臺運行方式啓動爲例,命令以下:

# /root/flaskDemo/app.py表示項目根路徑下的app.py啓動入口文件路徑
# /root/flaskDemo/flaskDemo.log表示輸出的日誌文件路徑
nohup python3 /root/flaskDemo/app.py >/root/flaskDemo/flaskDemo.log 2>&1 &

Linux下啓動項目

OK,經過以上內容,咱們已經成功將MySQL引入到咱們的接口項目中,並能夠成功進行接口請求,相關代碼已上傳到GitHub,你們有興趣的能夠基於此進行簡單部署及開展接口測試。

GitHub源碼地址:https://github.com/wintests/flaskDemo

相關文章
相關標籤/搜索