书接上文更多的有关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
回到目录