准备知识

DBUtils模块  <<-----重点

  1. DBUtilsPython的一个用于实现数据库连接池的模块
  2.  
  3. 此连接池有两种连接模式:
  4.  
  5. DBUtils提供两种外部接口:
  6. PersistentDB :提供线程专用的数据库连接,并自动管理连接。
  7. PooledDB :提供线程间可共享的数据库连接,并自动管理连接。
  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, # 链接池中最多共享的链接数量,0和None表示全部共享。PS: 无用,因为pymysql和MySQLdb等模块的 threadsafety都为1,所有值无论设置为多少,_maxcached永远为0,所以永远是所有链接都共享。
  10. blocking=True, # 连接池中如果没有可用连接后,是否阻塞等待。True,等待;False,不等待然后报错
  11. maxusage=None, # 一个链接最多被重复使用的次数,None表示无限制
  12. setsession=[], # 开始会话前执行的命令列表。
  13. ping=0,
  14. # ping MySQL服务端,检查是否服务可用。
  15. host='127.0.0.1',
  16. port=3306,
  17. user='root',
  18. password='',
  19. database='youku',
  20. charset='utf8',
  21. autocommit = True
  22. )

DBUtils,配置模板

  1. def func():
  2. ...
  3. conn = POOL.connection()
  4. ...

元类概念回顾(>>传送门点这里<<)

  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. # @Time : 2018/05/17 8:25
  4. # @Author : MJay_Lee
  5. # @File : 列表推导式.py
  6. # @Contact : limengjiejj@hotmail.com
  7. egg_list = []
  8. for i in range(10):
  9. egg_list.append('egg%s' % i)
  10.  
  11. print(egg_list)
  12. # ['egg0', 'egg1', 'egg2', 'egg3', 'egg4', 'egg5', 'egg6', 'egg7', 'egg8', 'egg9']
  13.  
  14. egg_list2 = ['egg%s' % i for i in range(10)]
  15. print(egg_list2)

列表推导式

  1. class Foo:
  2. x=1
  3. def __init__(self,y):
  4. self.y=y
  5.  
  6. def __getattr__(self, item):
  7. print('----> from getattr:你找的属性不存在')
  8.  
  9. def __setattr__(self, key, value):
  10. print('----> from setattr')
  11. # self.key=value #这就无限递归了,你好好想想
  12. # self.__dict__[key]=value #应该使用它
  13.  
  14. def __delattr__(self, item):
  15. print('----> from delattr')
  16. # del self.item #无限递归了
  17. self.__dict__.pop(item)
  18.  
  19. #__setattr__添加/修改属性会触发它的执行
  20. f1=Foo(10)
  21. print(f1.__dict__) # 因为你重写了__setattr__,凡是赋值操作都会触发它的运行,你啥都没写,就是根本没赋值,除非你直接操作属性字典,否则永远无法赋值
  22. f1.z=3
  23. print(f1.__dict__)
  24.  
  25. #__delattr__删除属性的时候会触发
  26. f1.__dict__['a']=3#我们可以直接修改属性字典,来完成添加/修改属性的操作
  27. del f1.a
  28. print(f1.__dict__)
  29.  
  30. #__getattr__只有在使用点调用属性且属性不存在的时候才会触发
  31. f1.xxxxxx

__getattr__,__setattr__

补充:

  1. class Foo:
  2. def __init__(self,x):
  3. self.x=x
  4.  
  5. def __getattr__(self, item):
  6. print('执行的是我')
  7. # return self.__dict__[item]
  8. def __getattribute__(self, item):
  9. print('不管是否存在,我都会执行')
  10. raise AttributeError('哈哈')
  11.  
  12. f1=Foo(10)
  13. f1.x
  14. f1.xxxxxx
  15.  
  16. #当__getattribute__与__getattr__同时存在,只会执行__getattrbute__,除非__getattribute__在执行过程中抛出异常AttributeError

区分__getattr__,__getattribute__

反射(update和save两个功能代码里,拼接SQL语句时,给参数赋值时时需要用上):

  1. def getattr(object, name, default=None): # known special case of getattr
  2. """
  3. getattr(object, name[, default]) -> value
  4.  
  5. Get a named attribute from an object; getattr(x, 'y') is equivalent to x.y.
  6. When a default argument is given, it is returned when the attribute doesn't
  7. exist; without it, an exception is raised in that case.
  8. """
  9. pass
  10.  
  11. def setattr(x, y, v): # real signature unknown; restored from __doc__
  12. """
  13. Sets the named attribute on the given object to the specified value.
  14.  
  15. setattr(x, 'y', v) is equivalent to ``x.y = v''
  16. """
  17. pass
  18.  
  19. def delattr(x, y): # real signature unknown; restored from __doc__
  20. """
  21. Deletes the named attribute from the given object.
  22.  
  23. delattr(x, 'y') is equivalent to ``del x.y''
  24. """
  25. pass

getattr及其它相关属性

  1. class BlackMedium:
  2. feature='Ugly'
  3. def __init__(self,name,addr):
  4. self.name=name
  5. self.addr=addr
  6.  
  7. def sell_house(self):
  8. print('%s 黑中介卖房子啦,傻逼才买呢,但是谁能证明自己不傻逼' %self.name)
  9. def rent_house(self):
  10. print('%s 黑中介租房子啦,傻逼才租呢' %self.name)
  11.  
  12. b1=BlackMedium('万成置地','回龙观天露园')
  13.  
  14. #检测是否含有某属性
  15. print(hasattr(b1,'name'))
  16. print(hasattr(b1,'sell_house'))
  17.  
  18. #获取属性
  19. n=getattr(b1,'name')
  20. print(n)
  21. func=getattr(b1,'rent_house')
  22. func()
  23.  
  24. # getattr(b1,'aaaaaaaa') #报错
  25. print(getattr(b1,'aaaaaaaa','不存在啊'))
  26.  
  27. #设置属性
  28. setattr(b1,'sb',True)
  29. setattr(b1,'show_name',lambda self:self.name+'sb')
  30. print(b1.__dict__)
  31. print(b1.show_name(b1))
  32.  
  33. #删除属性
  34. delattr(b1,'addr')
  35. delattr(b1,'show_name')
  36. delattr(b1,'show_name111')#不存在,则报错
  37.  
  38. print(b1.__dict__)

类与对象的四个操作属性示例

操作类与对象的属性的补充:

  1. class Foo:
  2.  
  3. def __del__(self):
  4. print('执行我啦')
  5.  
  6. f1=Foo()
  7. del f1
  8. print('------->')
  9.  
  10. #输出结果
  11. 执行我啦
  12. ------->
  13.  
  14. ----------------------以下是另一种情况
  15. class Foo:
  16.  
  17. def __del__(self):
  18. print('执行我啦')
  19.  
  20. f1=Foo()
  21. # del f1
  22. print('------->')
  23.  
  24. #输出结果
  25. ------->
  26. 执行我啦
  27.  
  28. 典型的应用场景:
  29.  
  30. 创建数据库类,用该类实例化出数据库链接对象,对象本身是存放于用户空间内存中,而链接则是由操作系统管理的,存放于内核空间内存中
  31.  
  32. 当程序结束时,python只会回收自己的内存空间,即用户态内存,而操作系统的资源则没有被回收,这就需要我们定制__del__,在对象被删除前向操作系统发起关闭数据库链接的系统调用,回收资源

析构函数,__del__方法

  1. format_dict={
  2. 'nat':'{obj.name}-{obj.addr}-{obj.type}',#学校名-学校地址-学校类型
  3. 'tna':'{obj.type}:{obj.name}:{obj.addr}',#学校类型:学校名:学校地址
  4. 'tan':'{obj.type}/{obj.addr}/{obj.name}',#学校类型/学校地址/学校名
  5. }
  6. class School:
  7. def __init__(self,name,addr,type):
  8. self.name=name
  9. self.addr=addr
  10. self.type=type
  11.  
  12. def __repr__(self):
  13. return 'School(%s,%s)' %(self.name,self.addr)
  14. def __str__(self):
  15. return '(%s,%s)' %(self.name,self.addr)
  16.  
  17. def __format__(self, format_spec):
  18. # if format_spec
  19. if not format_spec or format_spec not in format_dict:
  20. format_spec='nat'
  21. fmt=format_dict[format_spec]
  22. return fmt.format(obj=self)
  23.  
  24. s1=School('oldboy1','北京','私立')
  25. print('from repr: ',repr(s1))
  26. print('from str: ',str(s1))
  27. print(s1)
  28.  
  29. '''
  30. str函数或者print函数--->obj.__str__()
  31. repr或者交互式解释器--->obj.__repr__()
  32. 如果__str__没有被定义,那么就会使用__repr__来代替输出
  33. 注意:这俩方法的返回值必须是字符串,否则抛出异常
  34. '''
  35. print(format(s1,'nat'))
  36. print(format(s1,'tna'))
  37. print(format(s1,'tan'))
  38. print(format(s1,'asfdasdffd'))

自定义打印格式,__str__方法

单例 (>>传送门点这里<<)

  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. # @Time : 2018/04/18 17:47
  4. # @Author : MJay_Lee
  5. # @File : 单例.py
  6. # @Contact : limengjiejj@hotmail.com
  7.  
  8. # 基于元类实现单例模式
  9. # 单例:即单个实例,指的是同一个类实例化多次的结果指向同一个对象,用于节省空间(场景:假若从配置文件中读取配置来进行实例化,在配置相同的情况下,就没必要重复产生对象浪费内存了)
  10.  
  11. # 方式一:定义一个类方法实现单例模式
  12. # import setting
  13. #
  14. # class Mysql:
  15. # instance = None
  16. # def __init__(self,host,port):
  17. # self.host = host
  18. # self.port = port
  19. #
  20. # @classmethod
  21. # def from_conf(self):
  22. # if not Mysql.instance:
  23. # res = Mysql(setting.HOST, setting.PORT)
  24. # Mysql.instance = res
  25. # return Mysql.instance
  26. #
  27. # # con1 = Mysql('127.0.0.1',80) # <__main__.Mysql object at 0x000000A9F7FC7978>
  28. # # con2 = Mysql('127.0.0.1',80) # <__main__.Mysql object at 0x000000A9F7FD8710>
  29. # # con3 = Mysql('127.0.0.1',80) # <__main__.Mysql object at 0x000000A9F7E09C88>
  30. # # print(con1,con2,con3)
  31. # #
  32. #
  33. # # con1 = Mysql.from_conf() # <__main__.Mysql object at 0x000000BB72BA4DD8>
  34. # # con2 = Mysql.from_conf() # <__main__.Mysql object at 0x000000BB72BA4E48>
  35. # # con3 = Mysql.from_conf() # <__main__.Mysql object at 0x000000BB72BA4E80>
  36. # # print(con1,con2,con3)
  37. #
  38. # con1 = Mysql.from_conf() # <__main__.Mysql object at 0x000000BD5BBA4DD8>
  39. # con2 = Mysql.from_conf() # <__main__.Mysql object at 0x000000BD5BBA4DD8>
  40. # con3 = Mysql.from_conf() # <__main__.Mysql object at 0x000000BD5BBA4DD8>
  41. # print(con1 is con2 is con3) # True
  42.  
  43. # # 方式二:定制元类实现
  44. # # 若从配置文件取相同配置产生对象则实现单例,若传值则新建对象
  45. import setting
  46.  
  47. class Mymeta(type):
  48. def __init__(self,name,bases,dic): # 定义类Mysql时就触发
  49.  
  50. # 事先从配置文件中取配置来造一个Mysql的实例出来
  51. self.__instance = object.__new__(self) # 产生对象
  52. self.__init__(self.__instance,setting.HOST,setting.PORT) # 初始化对象
  53. #上述两步可合并下面一步
  54. # self.__instance = super().__call__(*args,**kwargs)
  55.  
  56. super().__init__(name,bases,dic)
  57.  
  58. def __call__(self, *args, **kwargs): # Mysql(...)时触发
  59. if args or kwargs: # Mymeta类的对象括号内传值则新建obj,否则返回self.__instance
  60. obj = object.__new__(self)
  61. self.__init__(obj,*args,**kwargs)
  62. return obj
  63. return self.__instance
  64.  
  65. # Mysql = Mymeta('Mysql',(obj,),class_dic)
  66. class Mysql(metaclass=Mymeta):
  67. def __init__(self,host,port):
  68. self.host = host
  69. self.port = port
  70.  
  71. con1 = Mysql()
  72. con2 = Mysql()
  73. # con3 = Mysql() # <__main__.Mysql object at 0x0000008BA7E24DD8>
  74. # con4 = Mysql('127.0.0.1',80) # <__main__.Mysql object at 0x0000004B4B904EF0>,若Mymeta类的对象(Mysql)括号内传值则新建obj
  75. # print(con4) # True
  76.  
  77. # 装饰器实现单例
  78. # import setting
  79. #
  80. # def single_obj(cls):
  81. # __instance = cls(setting.HOST,setting.PORT)
  82. # def wrapper(*args, **kwargs):
  83. # if args or kwargs:
  84. # obj = cls(*args, **kwargs)
  85. # return obj
  86. # return __instance
  87. # return wrapper
  88. #
  89. # @single_obj
  90. # class Mysql:
  91. # def __init__(self,host,port):
  92. # self.host = host
  93. # self.port = port
  94. #
  95. # con1 = Mysql() # <__main__.Mysql object at 0x0000001F978D9C88>
  96. # con2 = Mysql() # <__main__.Mysql object at 0x0000001F978D9C88>
  97. # con3 = Mysql('127.0.0.1',80) # <__main__.Mysql object at 0x0000001F98AE4DD8>
  98. #
  99. # print(con1 is con2) # True

三个方法实现单例--示例


ORM简介

ORM即Object Relational Mapping,全称对象关系映射
当我们需要对数据库进行操作时,势必需要通过连接数据、调用sql语句、执行sql语句等操作,ORM将数据库中的表,字段,行与我们面向对象编程的类及其方法,属性等一一对应,即将该部分操作封装起来,程序猿不需懂得sql语句即可完成对数据库的操作。

一、知识储备:

1、在实例化一个user对象的时候,可以user=User(name='lqz',password='123')

2 也可以 user=User()

    user['name']='lqz'
    user['password']='123'
3 也可以 user=User()

    user.name='lqz'
    user.password='password'

前两种,可以通过继承字典dict来实现,第三种,用getattr和setattr:

__getattr__ 拦截点号运算。当对未定义的属性名称和实例进行点号运算时,就会用属性名作为字符串调用这个方法。如果继承树可以找到该属性,则不调用此方法

__setattr__会拦截所有属性的的赋值语句。如果定义了这个方法,self.arrt = value 就会变成self,__setattr__("attr", value).这个需要注意。当在__setattr__方法内对属性进行赋值是,不可使用self.attr = value,因为他会再次调用self,__setattr__("attr", value),则会形成无穷递归循环,最后导致堆栈溢出异常。应该通过对属性字典做索引运算来赋值任何实例属性,也就是使用self.__dict__['name'] = value

 二、定义Model基类

  1. # 在ModelsMetaclass中自定义拦截实例化对象的方法
  2. class Models(dict,metaclass=ModelsMetaclass):
  3. # k,v形式的值
  4. def __init__(self,**kwargs):
  5. super().__init__(**kwargs)
  6.  
  7. # 写存
  8. def __setattr__(self, key, value):
  9. self[key] = value
  10.  
  11. # 读取
  12. def __getattr__(self, item):
  13. try:
  14. return self[item]
  15. except KeyError:
  16. raise ('没有该属性')

三、定义Field

数据库中每一列数据,都有:列名,列的数据类型,是否是主键,默认值

  1. # 表示一个列:列名,列的类型,列的主键和默认值
  2. class Field:
  3. def __init__(self,name,column_type,primary_key,default):
  4. self.name = name
  5. self.column_type = column_type
  6. self.primary_key = primary_key
  7. self.default = default
  8.  
  9. class StringField(Field):
  10. def __init__(self,name=None,column_type='varchar(200)',primary_key=False,default=None):
  11. super().__init__(name,column_type,primary_key,default)
  12.  
  13. class IntegerField(Field):
  14. def __init__(self,name=None,column_type='int',primary_key=False,default=None):
  15. super().__init__(name,column_type,primary_key,default)

四、定义元类

数据库中的每个表,都有表名,每一列的列名,以及主键是哪一列

既然我要用数据库中的表,对应这一个程序中的类,那么我这个类也应该有这些类属性

但是不同的类这些类属性又不尽相同,所以我应该怎么做?在元类里拦截类的创建过程,然后把这些东西取出来,放到类里面

  1. class ModelsMetaclass(type):
  2. def __new__(cls,name,bases,attrs):
  3.  
  4. if name == 'Models': #
  5. return type.__new__(cls, name, bases, attrs)
  6. table_name = attrs.get('table_name', None) #字典取值,中括号或.get
  7. if not table_name:
  8. table_name = name
  9.  
  10. primary_key = None
  11. mappings = dict()
  12. for k, v in attrs.items():
  13. if isinstance(v, Field): # v 是不是Field的对象
  14. mappings[k] = v
  15. if v.primary_key: # v是基类对象,即判断该字段的主键
  16.  
  17. # 找到主键
  18. if primary_key:
  19. raise TypeError('主键重复:%s' % k)
  20. primary_key = k
  21.  
  22. for k in mappings.keys():
  23. attrs.pop(k) # 执行完此步后,attrs中只剩余有__属性__
  24. if not primary_key:
  25. raise TypeError('没有主键')
  26. attrs['table_name'] = table_name
  27. attrs['primary_key'] = primary_key
  28. attrs['mappings'] = mappings
  29. return type.__new__(cls, name, bases, attrs)

五、基于pymysql的数据库操作类(单例)

  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. # @Time : 2018/05/15 10:44
  4. # @Author : MJay_Lee
  5. # @File : mysql_singleton.py
  6. # @Contact : limengjiejj@hotmail.com
  7.  
  8. import pymysql
  9.  
  10. class Mysql_interface:
  11. __instense = None
  12. def __init__(self):
  13. self.conn = pymysql.connect(
  14. host = '127.0.0.1',
  15. port = 3306,
  16. user = 'root',
  17. password = '',
  18. charset = 'utf8',
  19. database = 'youku',
  20. autocommit = True
  21. )
  22. self.cursor = self.conn.cursor(cursor=pymysql.cursors.DictCursor)
  23.  
  24. def close_db(self):
  25. self.cursor.close()
  26. self.conn.close()
  27.  
  28. def select(self,sql,args):
  29. self.cursor.execute(sql,args)
  30. re = self.cursor.fetchall()
  31.  
  32. return re
  33.  
  34. def execute(self,sql,args):
  35. try:
  36. self.cursor.execute(sql,args)
  37. affected = self.cursor.rowcount
  38. except BaseException as e:
  39. print(e)
  40. return affected
  41.  
  42. @classmethod
  43. def singleton(cls):
  44. if not cls.__instense:
  45. cls.__instense = cls()
  46. return cls.__instense
  47.  
  48. if __name__ == '__main__':
  49. ms = Mysql_interface()
  50. re = ms.select('select * from user where id = %s',1)
  51. print(re)

六、继续Models基类

Models类是所有要对应数据库表类的基类,所以,Models的元类应该是咱们上面写的那个

而每个数据库表对应类的对象,都应该有查询、插入、保存,方法

所以:

  1. # 在ModelsMetaclass中自定义拦截实例化对象的方法
  2. class Models(dict,metaclass=ModelsMetaclass):
  3. # k,v形式的值
  4. def __init__(self,**kwargs):
  5. super().__init__(**kwargs)
  6.  
  7. # 写存
  8. def __setattr__(self, key, value):
  9. self[key] = value
  10.  
  11. # 读取
  12. def __getattr__(self, item):
  13. try:
  14. return self[item]
  15. except KeyError:
  16. raise ('没有该属性')
  17.  
  18. @classmethod
  19. def select_one(cls,**kwargs):
  20. '''
  21. 查一条
  22. :param kwargs:
  23. :return:
  24. '''
  25. key = list(kwargs.keys())[0]
  26. value = kwargs[key]
  27.  
  28. # select * from user where id=%s
  29. sql = 'select * from %s where %s =?' % (cls.table_name,key)
  30. sql = sql.replace('?','%s')
  31. ms = mysql_singleton.Mysql_interface().singleton()
  32. re = ms.select(sql,value) # 得到re字典对象
  33. if re:
  34. # attrs = {'name':'lmj','password':123}
  35. # User(**attrs)
  36. # 相当于 User(name='lmj',password=123)
  37. return cls(**re[0])
  38. else:
  39. return
  40.  
  41. @classmethod
  42. def select_many(cls, **kwargs):
  43. '''
  44. 查多条
  45. :param kwargs:
  46. :return:
  47. '''
  48. ms = mysql_singleton.Mysql_interface().singleton()
  49. if kwargs:
  50. key = list(kwargs.keys())[0]
  51. value = kwargs[key]
  52.  
  53. sql = 'select * from %s where %s =?' % (cls.table_name, key)
  54. sql = sql.replace('?', '%s')
  55. re = ms.select(sql, value) # 得到re字典对象
  56. else:
  57. sql = 'select * from %s' % (cls.table_name)
  58. re = ms.select(sql)
  59. if re:
  60. obj_list = [cls(**r) for r in re]
  61. return obj_list
  62. else:
  63. return
  64.  
  65. def update(self):
  66. ms = mysql_singleton.Mysql_interface().singleton()
  67. # update user set name = ?,password = ? where id = ?
  68.  
  69. filed_data = [] # name = ?,password = ?
  70. pr = None
  71. args = [] # 字段的值
  72. for k,v in self.mappings.items():
  73. if v.primary_key:
  74. pr = getattr(self,v.name,v.default)
  75. else:
  76. filed_data.append(v.name + '=?')
  77. args.append(getattr(self,v.name,v.default))
  78.  
  79. sql = 'update %s set %s where %s = %s' % (self.table_name,','.join(filed_data),self.primary_key,pr)
  80. sql = sql.replace('?','%s')
  81. ms.execute(sql,args)
  82.  
  83. def save(self):
  84. ms = mysql_singleton.Mysql_interface().singleton()
  85. # insert into user(name,password) values (?,?)
  86. field_data = []
  87. args = []
  88. value_data = []
  89. for k,v in self.mappings.items():
  90. if not v.primary_key:
  91. field_data.append(v.name)
  92. args.append(getattr(self,v.name,v.default))
  93. value_data.append('?')
  94.  
  95. sql = 'insert into %s(%s) VALUES (%s)' % (self.table_name,','.join(field_data),','.join(value_data))
  96. sql = sql.replace('?','%s')
  97. ms.execute(sql,args)

数据库池版,orm_pool的配置:

  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, # 链接池中最多共享的链接数量,0和None表示全部共享。PS: 无用,因为pymysql和MySQLdb等模块的 threadsafety都为1,所有值无论设置为多少,_maxcached永远为0,所以永远是所有链接都共享。
  10. blocking=True, # 连接池中如果没有可用连接后,是否阻塞等待。True,等待;False,不等待然后报错
  11. maxusage=None, # 一个链接最多被重复使用的次数,None表示无限制
  12. setsession=[], # 开始会话前执行的命令列表。
  13. ping=0,
  14. # ping MySQL服务端,检查是否服务可用。
  15. host='127.0.0.1',
  16. port=3306,
  17. user='root',
  18. password='',
  19. database='youku',
  20. charset='utf8',
  21. autocommit = True
  22. )
  23.  
  24. def func():
  25. # 检测当前正在运行连接数的是否小于最大链接数,如果不小于则:等待或报raise TooManyConnections异常
  26. # 否则
  27. # 则优先去初始化时创建的链接中获取链接 SteadyDBConnection。
  28. # 然后将SteadyDBConnection对象封装到PooledDedicatedDBConnection中并返回。
  29. # 如果最开始创建的链接没有链接,则去创建一个SteadyDBConnection对象,再封装到PooledDedicatedDBConnection中并返回。
  30. # 一旦关闭链接后,连接就返回到连接池让后续线程继续使用。
  31. conn = POOL.connection()
  32.  
  33. # print('链接被拿走了', conn._con)
  34. # print('池子里目前有', POOL._idle_cache, '\r\n')
  35.  
  36. cursor = conn.cursor()
  37. cursor.execute('select * from user')
  38. result = cursor.fetchall()
  39. print(result)
  40. conn.close()
  41.  
  42. if __name__ == '__main__':
  43.  
  44. func()

orm_pool.py

mysql_pool的配置:

  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. # @Time : 2018/05/15 10:44
  4. # @Author : MJay_Lee
  5. # @File : mysql_pool.py
  6. # @Contact : limengjiejj@hotmail.com
  7.  
  8. from video_web_mysql.orm_pool import orm_pool
  9. import pymysql
  10.  
  11. class Mysql_interface:
  12. def __init__(self):
  13. self.conn = orm_pool.POOL.connection()
  14. self.cursor = self.conn.cursor(cursor=pymysql.cursors.DictCursor)
  15.  
  16. def close_db(self):
  17. self.cursor.close()
  18. self.conn.close()
  19.  
  20. def select(self,sql,args=None):
  21. self.cursor.execute(sql,args)
  22. re = self.cursor.fetchall()
  23.  
  24. return re
  25.  
  26. def execute(self,sql,args):
  27. try:
  28. self.cursor.execute(sql,args)
  29. affected = self.cursor.rowcount
  30. except BaseException as e:
  31. print(e)
  32. return affected
  33.  
  34. if __name__ == '__main__':
  35. ms = Mysql_interface()
  36. re = ms.select('select * from user where id = %s',1)
  37. print(re)

mysql_pool.py

fuckorm的完整源码:

  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. # @Time : 2018/05/15 8:58
  4. # @Author : MJay_Lee
  5. # @File : fuckorm.py
  6. # @Contact : limengjiejj@hotmail.com
  7.  
  8. from video_web_mysql.orm_pool import mysql_pool
  9.  
  10. # 表示一个列:列名,列的类型,列的主键和默认值
  11. class Field:
  12. def __init__(self,name,column_type,primary_key,default):
  13. self.name = name
  14. self.column_type = column_type
  15. self.primary_key = primary_key
  16. self.default = default
  17.  
  18. class StringField(Field):
  19. def __init__(self,name=None,column_type='varchar(200)',primary_key=False,default=None):
  20. super().__init__(name,column_type,primary_key,default)
  21.  
  22. class IntegerField(Field):
  23. def __init__(self,name=None,column_type='int',primary_key=False,default=None):
  24. super().__init__(name,column_type,primary_key,default)
  25.  
  26. class ModelsMetaclass(type):
  27. def __new__(cls,name,bases,attrs):
  28.  
  29. if name == 'Models': #
  30. return type.__new__(cls, name, bases, attrs)
  31. table_name = attrs.get('table_name', None) #字典取值,中括号或.get
  32. if not table_name:
  33. table_name = name
  34.  
  35. primary_key = None
  36. mappings = dict()
  37. for k, v in attrs.items():
  38. if isinstance(v, Field): # v 是不是Field的对象
  39. mappings[k] = v
  40. if v.primary_key: # v是基类对象,即判断该字段的主键
  41.  
  42. # 找到主键
  43. if primary_key:
  44. raise TypeError('主键重复:%s' % k)
  45. primary_key = k
  46.  
  47. for k in mappings.keys():
  48. attrs.pop(k) # 执行完此步后,attrs中只剩余有__属性__
  49. if not primary_key:
  50. raise TypeError('没有主键')
  51. attrs['table_name'] = table_name
  52. attrs['primary_key'] = primary_key
  53. attrs['mappings'] = mappings
  54. return type.__new__(cls, name, bases, attrs)
  55.  
  56. # 在ModelsMetaclass中自定义拦截实例化对象的方法
  57. class Models(dict,metaclass=ModelsMetaclass):
  58. # k,v形式的值
  59. def __init__(self,**kwargs):
  60. super().__init__(**kwargs)
  61.  
  62. # 写存
  63. def __setattr__(self, key, value):
  64. self[key] = value
  65.  
  66. # 读取
  67. def __getattr__(self, item):
  68. try:
  69. return self[item]
  70. except KeyError:
  71. raise ('没有该属性')
  72.  
  73. @classmethod
  74. def select_one(cls,**kwargs):
  75. '''
  76. 查一条
  77. :param kwargs:
  78. :return:
  79. '''
  80. key = list(kwargs.keys())[0]
  81. value = kwargs[key]
  82.  
  83. # select * from user where id=%s
  84. sql = 'select * from %s where %s =?' % (cls.table_name,key)
  85. sql = sql.replace('?','%s')
  86. ms = mysql_pool.Mysql_interface()
  87. re = ms.select(sql,value) # 得到re字典对象
  88. if re:
  89. # attrs = {'name':'lmj','password':123}
  90. # User(**attrs)
  91. # 相当于 User(name='lmj',password=123)
  92. return cls(**re[0])
  93. else:
  94. return
  95.  
  96. @classmethod
  97. def select_many(cls, **kwargs):
  98. '''
  99. 查多条
  100. :param kwargs:
  101. :return:
  102. '''
  103. ms = mysql_pool.Mysql_interface()
  104. if kwargs:
  105. key = list(kwargs.keys())[0]
  106. value = kwargs[key]
  107.  
  108. sql = 'select * from %s where %s =?' % (cls.table_name, key)
  109. sql = sql.replace('?', '%s')
  110. re = ms.select(sql, value) # 得到re字典对象
  111. else:
  112. sql = 'select * from %s' % (cls.table_name)
  113. re = ms.select(sql)
  114. if re:
  115. obj_list = [cls(**r) for r in re]
  116. return obj_list
  117. else:
  118. return
  119.  
  120. def update(self):
  121. ms = mysql_pool.Mysql_interface()
  122. # update user set name = ?,password = ? where id = ?
  123.  
  124. filed_data = [] # name = ?,password = ?
  125. pr = None
  126. args = [] # 字段的值
  127. for k,v in self.mappings.items():
  128. if v.primary_key:
  129. pr = getattr(self,v.name,v.default)
  130. else:
  131. filed_data.append(v.name + '=?')
  132. args.append(getattr(self,v.name,v.default))
  133.  
  134. sql = 'update %s set %s where %s = %s' % (self.table_name,','.join(filed_data),self.primary_key,pr)
  135. sql = sql.replace('?','%s')
  136. ms.execute(sql,args)
  137.  
  138. def save(self):
  139. ms = mysql_pool.Mysql_interface()
  140. # insert into user(name,password) values (?,?)
  141. field_data = []
  142. args = []
  143. value_data = []
  144. for k,v in self.mappings.items():
  145. # 此处判断是否为自增主键,否则插入时避免还需手动输入主键ID
  146. if not v.primary_key:
  147. field_data.append(v.name)
  148. value_data.append('?')
  149. args.append(getattr(self, v.name, v.default))
  150.  
  151. sql = 'insert into %s(%s) VALUES (%s)' % (self.table_name,','.join(field_data),','.join(value_data))
  152. sql = sql.replace('?','%s')
  153. ms.execute(sql,args)
  154.  
  155. class User(Models):
  156. '''
  157. 首先赋值表名
  158. 其次根据数据库表结构来赋值
  159. '''
  160. table_name = 'user'
  161. # k v(Field的对象)
  162. id = IntegerField('id',primary_key=True)
  163. password = StringField('password')
  164.  
  165. class Notice(Models):
  166. table_name = 'notice'
  167. id = IntegerField('id',primary_key=True)
  168. name = StringField('name')
  169. content = StringField('content')
  170. user_id = IntegerField('user_id')
  171.  
  172. if __name__ == '__main__':
  173. # notice = Notice.select_one(id=1)
  174. # print(notice.content)
  175.  
  176. # notice_list = Notice.select_many(id=1)
  177. # print(notice_list)
  178.  
  179. # notice.name = '改变了'
  180. # notice.update()
  181.  
  182. notice = Notice(name='',content='新插入',user_id=1)
  183. notice.save()

fuckorm.py

增删改查,基础功能均亲测有效。

自己动手写一个简易对象关系映射,ORM(单例版和数据库池版)的更多相关文章

  1. 对象关系映射ORM

    对象关系映射(英语:Object Relational Mapping,简称ORM,或O/RM,或O/R mapping),是一种程序技术,用于实现面向对象编程语言里不同类型系统的数据之间的转换.从效 ...

  2. Android数据库框架——ORMLite轻量级的对象关系映射(ORM)Java包

    Android数据库框架--ORMLite轻量级的对象关系映射(ORM)Java包 事实上,我想写数据库的念头已经很久了,在之前写了一个答题系统的小项目那只是初步的带了一下数据库,数据库是比较强大的, ...

  3. Django 源码小剖: Django 对象关系映射(ORM)

    引 从前面已经知道, 一个 request 的到来和一个对应 response 的返回的流程, 数据处理和数据库离不开. 我们也经常在 views.py 的函数定义中与数据库打交道. django O ...

  4. Python 3 对象关系映射(ORM)

    ORM 对象关系映射 Object Relational Mapping 表 ---> 类 字段 ---> 属性 记录 ---> 对象 # mysql_client.py impor ...

  5. 通过java反射实现简单的关于MongoDB的对象关系映射(ORM).

    通过阅读MongoDB  3.2.1的官方文档中关于java 编程发现最新的文档并没有实现对对象到Document的映射,所以自己有了利用反射实现简单的关系映射. 1.定义抽象类:AbstractMo ...

  6. 对象关系映射 ORM

    1.1 作用 MTV框架中包括一个重要的部分,它实现了数据模型与数据库的解耦,即数据模型的设计不需要依赖于特定的数据库,通过简单的配置就可以轻松更换数据库,这极大的减轻了开发人员的工作量,不需要面对因 ...

  7. 对象关系映射(ORM)框架GreenDao简介和基本使用

    官网上的介绍,greenDAO 是一个将对象映射到 SQLite 数据库中的轻量且快速的 ORM 解决方案. GreenDao特点 性能最大化,可能是Android平台上最快的ORM框架 易于使用的A ...

  8. 对象-关系映射ORM(Object Relational Mapping)(转)

    ORM的实现思想就是将关系数据库中表的数据映射成对象,以对象的形式展现 Hibernate在实现ORM功能的时候主要用到的文件有:映射类(*.java).映射文件(*.hbm.xml)和数据库配置文件 ...

  9. 解析大型.NET ERP系统数据访问 对象关系映射框架LLBL Gen Pro

    LLBL Gen Pro是一个为.NET开发人员设计的的对象关系映射(ORM)框架,与NHibernate,Entity Framework等框架一样,通过实体与数据表的映射,实现关系数据库持久化. ...

随机推荐

  1. Cloudera Manager5安装总结遇到问题及解决办法 CDH 5.8 on CentOS 7

    问题导读:1.Cloudera Manager在线安装你认为有什么优点和缺点?2.Cloudera Manager安装过程中遇到,你认为该如何解决?3.在线安装addr.arpa domain nam ...

  2. Recovering InnoDB table from an .ibd file.

    Recovering an InnoDB table from only an .ibd file. Sometime you may need to recover a table when all ...

  3. Redis的基本操作语句

    注:以下出现的key.value都需要具体 1.String类型的数据存储获取 set key value:设置key的值为value,若存在则覆盖,不存在则自动创建decrby get key:获取 ...

  4. JUnit测试模块使用

    JUnit简介 ​ JUnit是一个Java语言的单元测试框架.它由Kent Beck和Erich Gamma建立,逐渐成为源于Kent Beck的sUnit的xUnit家族中最为成功的一个. JUn ...

  5. Android实现身份证拍摄框

    http://blog.csdn.net/lhbtm/article/details/55505668 最近项目需要实现身份证拍照的功能,系统的相机并不能满足需求,故需要自定义相机,先上效果图,使用了 ...

  6. [翻译] KGModal

    KGModal KGModal is an easy drop in control that allows you to display any view in a modal popup. The ...

  7. Java学习---JDK的安装和配置

    控制面板\系统和安全\系统 CLASSPATH %JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar; JAVA_HOME C:\Program Files ...

  8. Kali Nethunter初体验

    1.官网环境要求:n5 n7 n10 android 4.4 2.实验设备: N7 android 4.4.4 N7 android 4.4.3 N5 nadroid 4.4.2 3.开发者模式+us ...

  9. ubuntu 13.04添加 flash_plugin

    mv libflashplayer.so  /usr/lib/mozilla/plugins

  10. java多态抽象类实例

    编写一个Soldier类,描述具有普遍行为和属性的一个士兵对象. 编写陆军士兵.海军士兵.军官类来扩展Soldier类. 设计Soldier类的相关属性和方法. 建模几个陆军士兵.海军士兵.军官类来继 ...