这几天用了两种python调用数据库的写法,分别是通过pymysql调用了mysql、通过SQLAlchemy调用了sqlite3,感觉各有优缺点,总结一下
首先,通过pymysql的话,就是连接上数据库后输入自己定义的sql语句来直接操作数据库,优点是逻辑比较清晰,因为就等于是直接用sql语句操作数据库。
但问题也有很多:
- 语句会比较繁琐,每实现一个新功能就要写不同的sql语句
- 项目需要修改以达到不同目的时比较麻烦
- 需要学一点sql的语法,而且代码自解释性不强,要写注释
这里贴一个我为了操作数据库写的类:
class sql: def __init__(self, User): self.db = pymysql.connect("localhost", "steam-key", "duyakey", "steam-key") self.cursor = self.db.cursor() self.username = User def add_key(self, Name, Key): sql = "INSERT INTO `%s`(`name`, `key`)\ VALUES ('%s', '%s')" try: self.cursor.execute(sql % (self.username, Name, Key)) self.db.commit() #print("add success") except Exception as e: self.db.rollback() # 如果发生错误则回滚 print(e) finally: self.db.close() def get_key(self): list = [] sql = "SELECT * FROM `%s` WHERE 1" try: self.cursor.execute(sql % (self.username)) results = self.cursor.fetchall() #arr to dict for row in results: list.append(data_dict(row[0], row[1]).__dict__) #dict to json #print(list) except Exception as e: print(e) finally: self.db.close() return list def del_key(self, Name): sql = "DELETE FROM `%s` WHERE `name` = '%s'" try: self.cursor.execute(sql % (self.username, Name)) self.db.commit() #print('delete successed') except Exception as e: self.db.rollback() print(e) finally: self.db.close() #根据用户名检索,若找到用户返回此用户密码,若找不到返回0 def user_login(self): sql = "SELECT * FROM `Users` WHERE 1" return_data = '' try: self.cursor.execute(sql) results = self.cursor.fetchall() for row in results: if self.username == row[0]: return_data = row[1] except Exception as e: print(e) finally: self.db.close() return return_data
可以看到,很多步骤重复,代码可读性差,移植性差
然后再来看看SQLAlchemy,它不是直接对数据库进行操作,而是通过了ORM,ORM是什么?这里抄一段定义:
Object Relation Mapping,最初主要描述的是程序中的Object对象和关系型数据库中Rlation关系(表)之间的映射关系,目前来说也是描述程序中对象和数据库中数据记录之间的映射关系的统称,是一种进行程序和数据库之间数据持久化的一种编程思想
大概就是程序里面的一个对象与数据库的一张表直接对应,在向数据库输入内容时,程序先修改这个对象,然后把这个对象提交给数据库;当需要读取数据库内容时,先把数据表复制给对象,然后从对象读取
这是建立的类(对象):
class User(db.Model): __tablename__ = 'login_users' user_id = db.Column(db.Integer,primary_key=True) name = db.Column(db.String(64),unique=True) password = db.Column(db.String(128),unique=True) login_count = db.Column(db.Integer,default=0) class Token(db.Model): __tablename__ = 'user_tokens' id = db.Column(db.Integer,primary_key=True) token = db.Column(db.String(17),unique=True) user_id = db.Column(db.Integer,db.ForeignKey("login_users.user_id")) user = db.relationship("User",backref="token")
ps:这两个类是一对多的关系,即表User中的每一个User对应到表Token中的一部分数据,在多用户下很实用
还有一个网上找到的很实用的函数,是用来把对象转换成python的dict的:
def row2dict(row): d = {} for column in row.__table__.columns: d[column.name] = str(getattr(row, column.name)) return d
我用了这么一小会,觉得它有这些缺点:
- 它的初始搭建过程比裸sql繁琐,首先你需要确定你的类(即对象)中的每一个值都与你的表对应,要是差一点就什么数据都看不到了
- 它的文档资料比裸sql少,且官方文档晦涩难懂,还是看看民间博客才稍微理解了点
当然,优点就是'!裸sql的缺点'了