灵虚御风
醉饮千觞不知愁,忘川来生空余恨!

导航

 

今日内容
orm

1. 数据库池orm  

2.单例orm

 

1. 数据库池orm  

文件夹:orm_pool

文件:db_pool.py

 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 )
View Code

 

文件:mysql_singleton.py

 文件:mysql_singleton.py
 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)
mysql_singleton

 

文件:orm.py

  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
orm

 

2.单例orm

文件夹:orm_singleton

文件:mysql_singleton.py

 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     '''
mysql_singleton

 

文件:orm.py

  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
orm

 

posted on 2019-07-01 18:58  没有如果,只看将来  阅读(241)  评论(0编辑  收藏  举报