数据库连接
import pymysql
class Mysql(object):
_instance = None
def init(self):
self.conn = pymysql.connect(
host = '127.0.0.1',
port = 3306,
user = 'root',
password = '',
database = 'day41',
charset = 'utf8',
autocommit = True
)
self.cursor = self.conn.cursor(pymysql.cursors.DictCursor)
def close_db(self):
self.cursor.close()
self.conn.close()
def select(self,sql,args=None):
self.cursor.execute(sql,args)
res = self.cursor.fetchall() # 注意一点:fetchall拿到的数据结构是一个列表套字典[{},{},{}]
return res
def execute(self,sql,args):
# insert into user(name,password) values('jason','123')
# update user set name='jason',passsword='456' where id=1
try:
self.cursor.execute(sql, args)
except BaseException as e:
print(e)
@classmethod
def singleton(cls):
if not cls._instance:
cls._instance = cls()
return cls._instance
ORM 代码
from mysql_signleton import Mysql
定义字段的父类,参数包括:字段名,类型,主键,默认值
class Field(object):
def init(self, name, colum_type, primary_key, default):
self.name = name
self.colum_type = colum_type
self.primary_key = primary_key
self.default = default
定义字符串类型的字段类
class StringField(Field):
def init(self, name, colum_type='varchar(32)', primary_key=False, default=None):
super().init(name,colum_type,primary_key,default)
定义整型了类型字段
class IntField(Field):
def init(self,name,colum_type='int',primary_key = False, default = None):
super().init(name,colum_type,primary_key,default)
class MyMetaClass(type):
def new(cls,class_name,class_bases,class_attrs):
# 定义的元类的是用来拦截modle的创建过程,modles并不是一个模型表,不需要创建过程
if class_name =='Modles':
return type.new(class_name,class_bases,class_attrs)
# 创建一个表,如果有新表名就用表名,没有就默认用类名
table_name = class_attrs.get('table_name',class_name)
primary_key = None
mappings = {}
for k,v in class_attrs.items(): # k: id,name v:IntField(),StringField()
# 拿出所有自定义的表的字段属性
if isinstance(v,Field):
# 将所有的自定义的表的字段存入字典中
mappings[k]=v
# 检验表的主键
if v.primary_key:
# 每个表只有一个主键
if primary_key:
raise TypeError('一张表只有一个属性')
primary_key = v.name
for k in mappings.keys():
# 将单个字段删除
class_attrs.pop(k)
# 检验用户自定义模型表是否指定主键字段
if not primary_key:
raise TypeError('一张表必须要有主键')
# 将标示表的特征信息,表名,表的主键字段,表的其他字段都塞到类的名称空间中
class_attrs['table_name'] = table_name
class_attrs['primary_key'] = primary_key
class_attrs['mapping'] = mappings
return type.__new__(cls,class_name,class_bases,class_attrs)
辅助类:方便实例化对象使用点方法,直接调用属性
class Modles(dict, metaclass=MyMetaClass):
# 继承字典的方法
def init(self,kwargs):
super().init(kwargs)
# 获取字典对应的值self = 字典
def __getattr__(self, item):
return self.get(item,'没有该键')
# 修改属性值
def __setattr__(self, key, value):
self[key] = value
@classmethod
def select(cls,**kwargs):
ms = Mysql.singleton()
if not kwargs:
sql = 'select * from %s'%cls.table_name
res = ms.select(sql)
else:
k = list(kwargs.keys())[0] # .keys 不能直接取值,可以迭代取值
v = kwargs.get(k)
sql = 'select * from %s where %s =?'%(cls.table_name,k)
sql = sql.replace('?','%s')
res = ms.select(sql,v)
if res:
return [cls(**r) for r in res]
if name == 'main':
class Teacher(Modles):
table_name = 'teacher'
tid = IntField(name='tid', primary_key=True)
tname = StringField(name='tname')
t1 = Teacher(tname='king',tid=1)
print(t1.tname)
print(t1.tid)