上一章我们对mysql进行了增删改查,接下来学习对postgresql的操作,postgresql是异步数据库,并且支持更多的数据类型,开源免费,对于postgresql的操作用的是psycopg2驱动,它和pymysql用法非常相似,只有两个地方有区别,在代码中有体现,因此在这里我们就简单的介绍一下,其他功能大家联想即可。
简单的普及一下知识:
在请求的过程中有的因为操作不当报各种错误
401 没有权限,这个我们接下来会遇到
403 表示资源不可用
404 就是你请求路径写错啦,意思是没有这个路由
405 请求方式不对,post请求,你非得用get,当然人家不会要啊
500 内部错误 就是你服务器代码错啦
一、准备工作
还记得我们在安装postgresql的时候建立的users表吗?我们用pgAdmin4看一下,简单的处理一下,更改一个字段名字。
在这里为了省事我们就在上一章的代码基础上更改,并且这里只用一张表来演示。在工程目录下的handler目录下新建psqlhandler.py文件。
二、写代码
1、对于psqlhandler.py文件我们做如下操作
from basehandler import BaseHandler
import psycopg2 #导入连接postgresql的驱动模块
# 数据库参数的一些字段是不一样的
# 主机名得换成你自己的哦
connect={
'host' : 'x.x.x.x',
'port' : 5432,
'user' : 'postgres',
'password' : 'postgres',
'database' : 'test'
}
class NewUserHandler(BaseHandler):
# 重写post请求函数,处理post请求
def post(self):
# 为了防止出错导致程序崩溃,我们需要捕获异常函数,并处理
try:
# 从请求中获取参数,如果获取不到,我们赋值 None
username = self.get_argument('username', None)
password = self.get_argument('password', None)
# 对传入的参数进行判断,如果为空我们回复 error,并终止执行下去
if not username:
# self.write()函数的参数为标准的json类型
self.write({"error":"用户账号为空!"})
return
if not password:
# self.write()函数的参数为标准的json类型
self.write({"error":"用户密码为空!"})
return
# 如果不为空那么开始访问数据库吧
# 首先是sql语句
sql = "insert into users(username,password) values('{0}','{1}')".format(username,password)
# 创建连接对象,相应的参数 意思依次为 主机ip 端口 数据库用户名 数据库用户密码 数据库名称
conn = psycopg2.connect(**connect)
# 创建连接游标,用于读写数据库
cursor = conn.cursor()
# 执行sql语句,并返回影响行数,这是和mysql不一样的地方
cursor.execute(sql)
# 返回影响的函数
effect_row = cursor.rowcount
# 提交数据
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 id,username,users.createtime from users where id={0}".format(user_id)
# 创建连接对象
conn = psycopg2.connect(**connect)
# 创建连接游标,用于读写数据库
cursor = conn.cursor()
# 执行sql语句,并返回影响行数
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')
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 id,username,users.createtime from users"
# 创建连接对象
conn = psycopg2.connect(**connect)
# 创建连接游标,用于读写数据库
cursor = conn.cursor()
# 执行sql语句,并返回影响行数
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_list.append(user_dir)
self.write({"success":user_list})
except Exception as e:
# 如果出现异常我们打印出来
print(e)
self.write({"error":"服务器出错!"})
# 这是一个处理更改用户信息的请求类,继承BaseHandler
# 这里我们只更改密码,如果你有想法的可以自己增加
class UpdateUserHandler(BaseHandler):
# 重写get请求函数,处理get请求
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 = psycopg2.connect(**connect)
# 创建连接游标,用于读写数据库
cursor = conn.cursor()
# 执行sql语句
cursor.execute(sql)
# 返回影响的函数
effect_row = cursor.rowcount
# 提交数据
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 = psycopg2.connect(**connect)
# 创建连接游标,用于读写数据库
cursor = conn.cursor()
# 执行sql语句
cursor.execute(sql)
# 返回影响的函数
effect_row = cursor.rowcount
# 提交数据
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":"服务器出错!"})
2、在mian.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
# 这是操作 postgresql 的路由
from psqlhandler 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),
(r"/psql/new", NewUserHandler),
(r"/psql/info", GetUserHandler),
(r"/psql/list", ListUserHandler),
(r"/psql/update", UpdateUserHandler),
(r"/psql/delete", DeleteUserHandler),
])
# 绑定端口,单进程启动
application.listen(8000)
tornado.ioloop.IOLoop.instance().start()
if __name__ == "__main__":
main()
三、测试一下
1、插入用户
2、查询用户
3、用户列表
4、更改用户信息
5、删除用户
我们看一下数据库
不知道你们有没有发现,我们对数据库的操作是通过sql语句实现的,当我们字段非常多的时候,sql语句特别的长,表与表之间关系多的时候,sql语句又特别的复杂,有没有一种简单的方式呢?下一章我们来学习。