今日内容
orm
1. 数据库池orm
2.单例orm
1. 数据库池orm
文件夹:orm_pool
文件:db_pool.py
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 from DBUtils.PooledDB import PooledDB 2 import pymysql 3 4 POOL = PooledDB( 5 creator=pymysql, # 使用链接数据库的模块 6 maxconnections=6, # 连接池允许的最大连接数,0和None表示不限制连接数 7 mincached=2, # 初始化时,链接池中至少创建的空闲的链接,0表示不创建 8 maxcached=5, # 链接池中最多闲置的链接,0和None不限制 9 maxshared=3, 10 # 链接池中最多共享的链接数量,0和None表示全部共享。PS: 无用,因为pymysql和MySQLdb等模块的 threadsafety都为1,所有值无论设置为多少,_maxcached永远为0,所以永远是所有链接都共享。 11 blocking=True, # 连接池中如果没有可用连接后,是否阻塞等待。True,等待;False,不等待然后报错 12 maxusage=None, # 一个链接最多被重复使用的次数,None表示无限制 13 setsession=[], # 开始会话前执行的命令列表。如:["set datestyle to ...", "set time zone ..."] 14 ping=0, 15 # ping MySQL服务端,检查是否服务可用。# 如:0 = None = never, 1 = default = whenever it is requested, 2 = when a cursor is created, 4 = when a query is executed, 7 = always 16 host='127.0.0.1', 17 port=3306, 18 user='root', 19 password='llx20190411', 20 database='youku_one', 21 charset='utf8', 22 autocommit='True' 23 )
文件:mysql_singleton.py
文件:mysql_singleton.py
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import pymysql 2 from orm_pool import db_pool 3 4 # 封装Mysql 5 ''' 6 instance实例 7 connect连接 8 autocommit自动提交 9 BaseException基本异常 10 connect和connection事件功能相似,但是被触发的时间不同.connect先于connetion. 11 connect是一旦有连接就被触发,而connection在连接完全建立后才被触发. 12 一般直接如同官网示例那样,直接使用connection事件即可. 13 但是为了保持与前端的一致性,全部使用connect事件也未尝不可. 14 参考资料: 15 https://socket.io/get-started... 16 https://stackoverflow.com/que... 17 ''' 18 class Mysql(object): 19 _instance = None 20 def __init__(self): 21 # 连接数据库 22 self.conn = db_pool.POOL.connection() 23 # 游标 24 self.cursor = self.conn.cursor(pymysql.cursors.DictCursor) 25 ''' 26 # 游标 27 self.cursor = self.conn.cursor() # 值为元组 () 28 # 增加 pymysql.cursors.DictCursor 29 # 游标 30 self.cursor = self.conn.cursor(pymysql.cursors.DictCursor) # 值为 列表套字典 31 # 变化原因:增加可读性,便于理解 32 ''' 33 34 # 运行一次SQL语句完成需要关闭连接和游标 35 def close(self): 36 self.cursor.close() 37 self.conn.close() 38 39 # 查询 40 def select(self,sql,args=None): 41 # 执行 42 self.cursor.execute(sql,args) 43 # 取出 44 res = self.cursor.fetchall() # 值 列表套字典 45 return res 46 47 # 执行--防止参数args引起的报错,增加健壮性 48 def execute(self,sql,args): 49 try: 50 self.cursor.execute(sql,args) 51 except BaseException as e: 52 print(e)
文件:orm.py
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 from orm_pool.mysql_singleton import Mysql 2 3 4 # 定义字段类(数据行) 5 class Field(object): 6 def __init__(self, name, column_type, primary_key, default): 7 self.name = name 8 self.column_type = column_type 9 self.primary_key = primary_key 10 self.default = default 11 12 13 # 定义具体的字段类(字符串数据行) 14 class StringField(Field): 15 def __init__(self, name, column_type='varchar(256)', primary_key=False, default=None): 16 super().__init__(name, column_type, primary_key, default) 17 18 19 class IntegerField(Field): 20 def __init__(self, name, column_type='int', primary_key=False, default=None): 21 super().__init__(name, column_type, primary_key, default) 22 23 24 # 元类的应用 (通过类来创建类) 这里主要是类创建表进行映射,并且设置限制信息 25 class ModelMetaClass(type): 26 ''' 27 __new__方法(重点) 28 元类中的new方法会在创建类对象时执行,并且先于init方法 29 作用是创建一个类对象 30 class A(metaclass=MyMetaClass): 31 pass 32 1.执行MyMetaClass的__new__方法 拿到一个类对象 33 2.执行MyMetaClass的__init__ 方法 传入类对象以及其他的属性 ,进行初始化 34 35 注意:如果覆盖了__new__ 一定也要调用type中的__new__并返回执行结果 36 37 attrs 名称空间 38 ''' 39 40 def __new__(cls, class_name, class_base, class_attrs): 41 # 我仅仅只想拦截模型表的创建过程(对表的参数进行限制) 42 if class_name == 'Models': 43 # 只在这个条件下修改出一个新的类 44 return type.__new__(cls, class_name, class_base, class_attrs) 45 # 给类放表名,主键字段,所有字段 46 # 给类放表名 47 table_name = class_attrs.get('table_name', class_name) 48 # 定义一个存储主键的变量 49 primary_key = None 50 # 定义一个字典用来存储自定义的表示表的所有字段信息 51 # 字段 == 列名 + 属性 + 是否有主键索引 + 是否有默认值 52 mappings = {} 53 # for循环 当前类的名称空间 54 for k, v in class_attrs.items(): 55 if isinstance(v, Field): 56 mappings[k] = v 57 if v.primary_key: 58 if primary_key: 59 raise TypeError('主键只能有一个') 60 primary_key = v.name 61 # 将mappings 中重复的键值删除 62 for k in mappings.keys(): 63 # pop 去重 64 class_attrs.pop(k) 65 if not primary_key: 66 raise TypeError('必须要有一个主键') 67 # 保存修改(将处理好的数据放入'class_attrs'中) 68 class_attrs['table_name'] = table_name 69 class_attrs['primary_key'] = primary_key 70 class_attrs['mappings'] = mappings 71 return type.__new__(cls, class_name, class_base, class_attrs) 72 73 74 # 创建出类,以及他的增删改查 75 ''' 76 # 反射 -------英文中叫反省 (自省) 77 1.面向对象中的反省: 78 指的是,一个对象必须具备,发现自身属性,以及修改自身属性的能力; 79 一个对象在设计初期,可能考虑不够周全后期需要删除或修改已经存在的属性, 和增加属性 80 # 反射就是通过字符串来操作对象属性 81 2.涉及到的方法: 82 ``` 83 hasattr 判断是否存在某个属性 84 getattr 获取某个属性的值 85 setattr 新增或修改某个属性 86 delattr 删除某个属性 87 88 # dict 字典可以把所有的值都存储进去 89 ''' 90 91 92 class Models(dict, metaclass=ModelMetaClass): 93 def __init__(self, **kwargs): 94 super().__init__(**kwargs) 95 96 # 获取表中属性的值 97 def __getattr__(self, item): 98 return self.get(item, '没有键值对') 99 100 # 新增或者修改表中的属性 101 def __setattr__(self, key, value): 102 self[key] = value 103 104 # 查(**kwargs 条件) 105 @classmethod 106 def select(cls, **kwargs): 107 ms = Mysql() 108 # select * from userinfo 109 if not kwargs: 110 sql = 'select * from %s' % cls.table_name 111 res = ms.select(sql) 112 else: 113 # select * from userinfo where id = 1 114 # 默认只取一个条件(自己设置一个站为符'?') 115 k = list(kwargs.keys())[0] 116 v = kwargs.get(k) 117 sql = 'select * from %s where %s=?' % (cls.table_name, k) 118 # select * from userinfo where id = ? 119 # 用'%s'替换'?'replace()替换 120 sql = sql.replace('?', '%s') 121 # select * from userinfo where id = %s 122 res = ms.select(sql, v) 123 124 # 将数据库的一条数据映射成类的对象 125 # **r 打散r 126 if res: 127 return [cls(**r) for r in res] 128 # 结果为 # 列名 + 属性 + 是否有主键索引 + 是否有默认值 129 130 # 增 131 def save(self): 132 ms = Mysql() 133 # insert into userinfo(name,password) values('jason','123') 134 # insert into %s(%s) values(?) 135 fields = [] # [name,password] 136 values = [] 137 args = [] 138 for k, v in self.mappings.items(): 139 # 将id字段去除 因为新增一条数据 id是自动递增的不需要你传 140 if not v.primary_key: 141 fields.append(v.name) # 列名 142 args.append('?') # 值数量 = 列数量 143 values.append(getattr(self, v.name)) 144 # insert into userinfo(name,password) values(?,?) 145 sql = 'insert into %s(%s) values(%s)' % (self.table_name, ','.join(fields), ','.join(args)) 146 # insert into userinfo(name,password) values(?,?) 147 # 用'%s'替换'?'replace()替换 148 sql = sql.replace('?', '%s') 149 ms.execute(sql,values) 150 #print(values,'收到吗里去了') 151 152 # 改:基于已经存在了的数据进行一个修改操作 153 def update(self): 154 ms = Mysql() 155 # update userinfo set name='jason',password='123' where id = 1 156 fields = [] # [name,password] 157 values = [] 158 pr = None 159 for k, v in self.mappings.items(): 160 if v.primary_key: 161 pr = getattr(self, v.name, v.default) 162 else: 163 fields.append(v.name + '=?') 164 values.append(getattr(self, v.name, v.default)) 165 sql = 'update %s set %s where %s = %s' % (self.table_name, ','.join(fields), self.primary_key, pr) 166 # update userinfo set name='?',password='?' where id = 1 167 sql = sql.replace('?', '%s') 168 ms.execute(sql, values) 169 170 171 # 运算测试是否正确 172 if __name__ == '__main__': 173 pass
2.单例orm
文件夹:orm_singleton
文件:mysql_singleton.py
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import pymysql 2 3 # 封装Mysql 4 ''' 5 instance实例 6 connect连接 7 autocommit自动提交 8 BaseException基本异常 9 ''' 10 class Mysql(object): 11 _instance = None 12 def __init__(self): 13 # 连接数据库 14 self.conn = pymysql.connect( 15 host = '127.0.0.1', 16 port = 3306, 17 user = 'root', 18 password = 'llx20190411', 19 datebase = 'youku_one', 20 charset = 'utf8', 21 autocommit = True 22 ) 23 # 游标 24 self.cursor = self.conn.cursor(pymysql.cursors.DictCursor) 25 ''' 26 # 游标 27 self.cursor = self.conn.cursor() # 值为元组 () 28 # 增加 pymysql.cursors.DictCursor 29 # 游标 30 self.cursor = self.conn.cursor(pymysql.cursors.DictCursor) # 值为 列表套字典 31 # 变化原因:增加可读性,便于理解 32 ''' 33 34 # 运行一次SQL语句完成需要关闭连接和游标 35 def close(self): 36 self.cursor.close() 37 self.conn.close() 38 39 # 查询 40 def select(self,sql,args=None): 41 # 执行 42 self.cursor.execute(sql,args) 43 # 取出 44 res = self.cursor.fetchall() # 值 列表套字典 45 return res 46 47 # 执行--防止参数args引起的报错,增加健壮性 48 def execute(self,sql,args): 49 try: 50 self.cursor.execute(sql,args) 51 except BaseException as e: 52 print(e) 53 # 单例 54 @classmethod 55 def singleton(cls): 56 if not cls._instance: 57 # 没有则创建新的实例并保存到类中 58 cls._instance = cls() 59 return cls._instance 60 61 ''' 62 singleton单例模式---避免重复创建对象,浪费资源,保证程序安全的前提 63 @classmethod(就是在封装中用'.'直接点出各种使用方式) 64 一般来说,调用某个类的方法,需要先生成一个实例,再通过实例调用方法。Java中有静态变量,静态方法,可以使用类直接进行调用。Python提供了两个修饰符@staticmethod @classmethod也可以达到类似效果。 65 单例: 66 某个类如果只有一个实例对象,那么该类成为单例类 67 单例的好处: 68 当某个类的所有对象特征和行为完全一样时,避免重复创建对象,浪费资源 69 cls._instance 类的实例 70 '''
文件:orm.py
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 from orm_singleton.mysql_singleton import Mysql 2 3 # 定义字段类(数据行) 4 class Field(object): 5 def __init__(self,name,column_type,primary_key,default): 6 self.name = name 7 self.column_type = column_type 8 self.primary_key = primary_key 9 self.default = default 10 11 # 定义具体的字段类(字符串数据行) 12 class StringField(Field): 13 def __init__(self,name,column_type='varchar(256)',primary_key=False,default=None): 14 super().__init__(name,column_type,primary_key,default) 15 16 class IntegerField(Field): 17 def __init__(self,name,column_type='int',primary_key=False,default=None): 18 super().__init__(name,column_type,primary_key,default) 19 20 # 元类的应用 (通过类来创建类) 这里主要是类创建表进行映射,并且设置限制信息 21 class ModelMetaClass(type): 22 ''' 23 __new__方法(重点) 24 元类中的new方法会在创建类对象时执行,并且先于init方法 25 作用是创建一个类对象 26 class A(metaclass=MyMetaClass): 27 pass 28 1.执行MyMetaClass的__new__方法 拿到一个类对象 29 2.执行MyMetaClass的__init__ 方法 传入类对象以及其他的属性 ,进行初始化 30 31 注意:如果覆盖了__new__ 一定也要调用type中的__new__并返回执行结果 32 33 attrs 名称空间 34 ''' 35 def __new__(cls,class_name,class_base,class_attrs): 36 #我仅仅只想拦截模型表的创建过程(对表的参数进行限制) 37 if class_name == 'Models': 38 # 只在这个条件下修改出一个新的类 39 return type.__new__(cls,class_name,class_base,class_attrs) 40 # 给类放表名,主键字段,所有字段 41 # 给类放表名 42 table_name = class_attrs.get('table_name',class_name) 43 # 定义一个存储主键的变量 44 primary_key = None 45 # 定义一个字典用来存储自定义的表示表的所有字段信息 46 # 字段 == 列名 + 属性 + 是否有主键索引 + 是否有默认值 47 mappings={} 48 # for循环 当前类的名称空间 49 for k,v in class_attrs.items(): 50 if isinstance(v,Field): 51 mappings[k] = v 52 if v.primary_key: 53 if primary_key: 54 raise TypeError('主键只能有一个') 55 primary_key = v.name 56 # 将mappings 中重复的键值删除 57 for k in mappings.keys(): 58 # pop 去重 59 class_attrs.pop(k) 60 if not primary_key: 61 raise TypeError('必须要有一个主键') 62 # 保存修改(将处理好的数据放入'class_attrs'中) 63 class_attrs['table_name'] = table_name 64 class_attrs['primary_key'] = primary_key 65 class_attrs['mappings'] = mappings 66 return type.__new__(cls,class_name,class_base,class_attrs) 67 68 # 创建出类,以及他的增删改查 69 ''' 70 # 反射 -------英文中叫反省 (自省) 71 1.面向对象中的反省: 72 指的是,一个对象必须具备,发现自身属性,以及修改自身属性的能力; 73 一个对象在设计初期,可能考虑不够周全后期需要删除或修改已经存在的属性, 和增加属性 74 # 反射就是通过字符串来操作对象属性 75 2.涉及到的方法: 76 ``` 77 hasattr 判断是否存在某个属性 78 getattr 获取某个属性的值 79 setattr 新增或修改某个属性 80 delattr 删除某个属性 81 82 # dict 字典可以把所有的值都存储进去 83 ''' 84 85 class Models(dict,metaclass=ModelMetaClass): 86 def __init__(self,**kwargs): 87 super().__init__(**kwargs) 88 89 #获取表中属性的值 90 def __getattr__(self,item): 91 return self.get(item,'没有键值对') 92 93 # 新增或者修改表中的属性 94 def __setattr__(self, key, value): 95 self[key] = value 96 97 # 查(**kwargs 条件) 98 @classmethod 99 def select(cls,**kwargs): 100 ms=Mysql.singleton() 101 # select * from userinfo 102 if not kwargs: 103 sql = 'select * from %s' % cls.table_name 104 res = ms.select(sql) 105 else: 106 # select * from userinfo where id = 1 107 # 默认只取一个条件(自己设置一个站为符'?') 108 k = list(kwargs.keys())[0] 109 v = kwargs.get(k) 110 sql = 'select * from %s where %s=?' % (cls.table_name,k) 111 # select * from userinfo where id = ? 112 #用'%s'替换'?'replace()替换 113 sql = sql.replace('?','%s') 114 # select * from userinfo where id = %s 115 res = ms.select(sql,v) 116 117 # 将数据库的一条数据映射成类的对象 118 # **r 打散r 119 if res: 120 return [cls(**r) for r in res] 121 # 结果为 # 列名 + 属性 + 是否有主键索引 + 是否有默认值 122 123 # 增 124 def save(self): 125 ms = Mysql.singleton() 126 # insert into userinfo(name,password) values('jason','123') 127 # insert into %s(%s) values(?) 128 fields = [] # [name,password] 129 values = [] 130 args = [] 131 for k,v in self.mappings.items(): 132 # 将id字段去除 因为新增一条数据 id是自动递增的不需要你传 133 if not v.primary_key: 134 fields.append(v.name) # 列名 135 args.append('?') # 值数量 = 列数量 136 values.append(getattr(self,v.name)) 137 # insert into userinfo(name,password) values(?,?) 138 sql = 'insert into %s(%s) values(%s)'%(self.table_name,','.join(fields),','.join(args)) 139 # insert into userinfo(name,password) values(?,?) 140 # 用'%s'替换'?'replace()替换 141 sql = sql.replace('?', '%s') 142 ms.execute(sql.values) 143 144 # 改:基于已经存在了的数据进行一个修改操作 145 def update(self): 146 ms = Mysql.singleton() 147 # update userinfo set name='jason',password='123' where id = 1 148 fields = [] # [name,password] 149 values = [] 150 pr = None 151 for k, v in self.mappings.items(): 152 if v.primary_key: 153 pr = getattr(self, v.name, v.default) 154 else: 155 fields.append(v.name + '=?') 156 values.append(getattr(self, v.name, v.default)) 157 sql = 'update %s set %s where %s = %s' % (self.table_name, ','.join(fields), self.primary_key, pr) 158 # update userinfo set name='?',password='?' where id = 1 159 sql = sql.replace('?', '%s') 160 ms.execute(sql, values) 161 162 163 # 运算测试是否正确 164 if __name__=='__main__': 165 pass