flask与DB交互


书接上文更多的有关FLASK API的事,我们了解到

  • 如何规范的创建一个Python项目
  • 如何规范的创建一个Resource对象
  • 如何加入TOKEN验证
  • 如何规范处理REQUEST请求
    接下里我们将把存在本地的数据规整的放到数据库里面去

示例代码

示例代码

SQLite

首先使用最简单的数据库SQLite来入门学习。

  • 创建虚拟环境
  • 安装必要的包(flask,Flask-RESTful,Flask-JWT)
    python内建是支持SQLite的,所以无需安装任何额外的依赖包(但是有时有些包可能对SQLite版本做了要求,我们需要重新安装更高版本的SQLite,鱼说的就是Django)
    一个测试,看看SQLite的用法
import sqlite3

connection = sqlite3.connect('data.db')

#创建一个游标,游标让我们可以执行DB的语句和方法,并且游标会记录下来所有的过程(举例,你在一个游标中执行了两个select,这样这个游标记录下来了你两次select的结果,并不是只存下最后一次)
cursor = connection.cursor()

#建表语句
create_table = '''
CREATE TABLE USERS (
    id int,
    username text,
    password text
);
'''
#创建表
# cursor.execute(create_table)

insert_query = '''
INSERT INTO USERS(id,username,password) VALUES (?,?,?);
'''
#执行单个参数
# user = (1,'Bomb','qsc')
# cursor.execute(insert_query,user)

#执行列表中所有的参数
# users = [
#     (2,'wolf','zse'),
#     (3,'cat','721126')
# ]
# cursor.executemany(insert_query,users)

select_query = '''
SELECT * from USERS;
'''
#cursor是一个迭代器,我们可以直接迭代取得内部所有结果集和所有的数据
for row in cursor.execute(select_query):
    print(row)
connection.commit()
cursor.close()
connection.close()

这里面粗略介绍了下如何用cursor执行和获得结果。
然后我们来更新原先的User类,让对象的创建都来自DB。user.py

import sqlite3
class User():
    def __init__(self, id, username, password):
        self.id = id
        self.username = username
        self.password = password

    #根据数据库内容获得用户对象
    @classmethod
    def find_by_username(cls,username):
        connection = sqlite3.connect('data.db')
        cursor = connection.cursor()

        query = '''
        SELECT * FROM USERS WHERE username = ?;
        '''
        result = cursor.execute(query,(username,))
        row = result.fetchone()
        if row:
            user = cls(*row)
        else:
            user = None
        cursor.close()
        connection.close()
        return user

    #根据数据库内容获得用户对象
    @classmethod
    def find_by_id(cls,_id):
        connection = sqlite3.connect('..\data.db')
        cursor = connection.cursor()

        query = '''
        SELECT * FROM USERS WHERE id = ?;
        '''
        result = cursor.execute(query,(_id,))
        row = result.fetchone()
        if row:
            user = cls(*row)
        else:
            user = None
        cursor.close()
        connection.close()
        return user

同时更正原先用户认证的逻辑security.py

def authenticate(username, password):
    user = User.find_by_username(username)
    if user and safe_str_cmp(user.password, password):
        return user

def identity(payload):
    user_id = payload['identity']
    return User.find_by_id(user_id)

登录和创建用户

在user.py新建一个类UserRegister,用来管理注册

class UserRegister(Resource):
    parser = reqparse.RequestParser()
    parser.add_argument('username',
        type=str,
        required=True,
        help="此字段不可以为空!"
    )
    parser.add_argument('password',
        type=str,
        required=True,
        help="此字段不可以为空!"
    )
    def post(self):
        data = UserRegister.parser.parse_args()
#剔除存在的username
        if User.find_by_username(data['username']) :
            return {'message':"A user with that username already exists."},400

        connection = sqlite3.connect('data.db')
        cursor = connection.cursor()
        
        query = '''
        INSERT INTO USERS VALUES (NULL,?,?)
        '''
        cursor.execute(query,(data['username'],data['password']))
#创建新用户
        connection.commit()
        cursor.close()
        connection.close()

        return {"message":"User created successfully."},201

接下来,调整整个文件的结构,让项目更像个项目


重构后的项目文档

现在项目文档已经和原教程不一样了,相对于原教程有三个注意点:

  • 文件或包名不要取code,这是python的内置包名
  • 讲app.py拖到最外面了,并将fast_api定义成一个包(即加上空文档init.py)
  • 将item的几个资源定义单独拉出来放在了.\fast_api\item.py

修改item.py,引用DB

然后我们创建items表,进一步修改item.py的逻辑

create_table = '''
CREATE TABLE IF NOT EXISTS items (name text PRIMARY KEY, price real)
'''
cursor.execute(create_table)

item.py就不贴了,可以直接看git。
这里补充一个优化:使用上下文管理器优化连接DB的操作

# 优化处理,上下文管理器
class SQLiteDB():
    #初始化连接,ignore_exc用作定义是否忽略错误
    def __init__(self,ignore_exc = False):
        print('__init__')
        self.ignore_exc = ignore_exc
        self.conn = None
        self.cursor = None
    #开启连接
    def __enter__(self):
        print('__enter__')
        try:
            self.conn = sqlite3.connect('data.db')
            self.cursor = self.conn.cursor()
            return self.cursor
        except Exception as ex:
            raise ex
    #关闭连接
    def __exit__(self, exc_type, exc_val, exc_tb):
        print('__exit__')
        try:
            #当发生错误时
            if not exc_type is None:
                self.conn.rollback()
                return self.ignore_exc
            else:
            #无异常,提交事务
                self.connection.commit()
        except Exception as ex:
            raise ex
        finally:
            #关闭连接
            self.cursor.close()
            self.conn.close()

这样的话,就可以直接用with关键词操作数据库链接

print("begin")
with SQLiteDB(ignore_exc = True) as curs:
    print("execute")
    arg2 = ['Avision']
    query = ('''
    select * from user where name = %s;
    ''')
    curs.execute(query,arg2)
    for row in curs:
        print(row.text)
print("end")

可以尝试执行,查看输出内容,再结合知识点理解

总结,我们学到了:
如何建立与DB——SQLite的连接
如何变更逻辑,建立表与数据的关系,让资料躺入DB
如何优化项目结构
如何用with优化DB的连接管理

课外阅读
关于Flask-JWT更多的故事

下一章
flask与SQLAlchemy

回到目录

你可能感兴趣的:(flask与DB交互)