手撸ORM系列
手撸ORM系列
实现了简单的orm框架,在封装好的pymysql及基础上,通过类与对象操作pymysql,对数据库进行管理与一些简单操作。
啥也不说,直接上代码!!!
one
封装好pymysql,是实现orm的基本。
# mysql_control.py
import pymysql
class Mysql:
# 单例模式
__instance = None
def __new__(cls, *args, **kwargs):
if not cls.__instance:
cls.__instance = object.__new__(cls)
return cls.__instance
def __init__(self):
self.mysql = pymysql.connect(
host='127.0.0.1',
port=3306,
user='root',
password='root',
database='orm_demo',
charset='utf8',
autocommit=True
)
self.cursor = self.mysql.cursor(pymysql.cursors.DictCursor)
def select(self, sql, args=None):
print(sql)
print(args)
# 提交select语句
self.cursor.execute(sql, args)
# 获取查询结果
res = self.cursor.fetchall()
return res
# 提交
def execute(self, sql, args):
try:
print(sql)
print(args)
self.cursor.execute(sql, args)
except Exception as e:
print(e)
def close(self):
self.cursor.close()
self.mysql.close()
two
封装基本的表字段,简单实现了整型与字符串类型。
# orm.py
class Field:
def __init__(self, name, column_type, primary_key, default):
self.name = name
self.column_type = column_type
self.primary_key = primary_key
self.default = default
class IntegerField(Field):
def __init__(self, name, column_type='int', primary_key=False, default=None):
super().__init__(name, column_type, primary_key, default)
class StringField(Field):
def __init__(self, name, column_type='varchar(64)', primary_key=False, default=None):
super().__init__(name, column_type, primary_key, default)
three
操作pymysql,实现简单的数据库操作。
# orm.py
class Model(dict, metaclass=Myorm):
def __init__(self, **kwargs):
super().__init__(**kwargs)
def __getattr__(self, item):
return self.get(item)
def __setattr__(self, key, value):
self[key] = value
@classmethod
def select(cls, **kwargs):
mysql = mysql_control.Mysql()
if not kwargs:
sql = 'select * from %s' % cls.table_name
res = mysql.select(sql)
else:
key = list(kwargs.keys())[0]
value = kwargs.get(key)
sql = 'select * from %s where %s=?' % (cls.table_name, key)
sql = sql.replace('?', '%s')
res = mysql.select(sql, value)
return [cls(**r) for r in res]
def save(self):
mysql = mysql_control.Mysql()
fields = []
values = []
replace = []
print(self.mappings)
for k, v in self.mappings.items():
fields.append(k)
values.append(
getattr(self, v.name, v.default)
)
replace.append('?')
sql = 'insert into %s(%s) values(%s)' % (self.table_name, ','.join(fields), ','.join(replace))
sql = sql.replace('?', '%s')
mysql.execute(sql, values)
def sql_update(self):
mysql = mysql_control.Mysql()
fields = []
values = []
primary_key = False
for k, v in self.mappings.items():
if v.primary_key:
primary_key = getattr(self, v.name)
else:
fields.append(v.name + '+?')
values.append(getattr(self, v.name))
sql = 'update %s set %s where %s=%s' % (self.table_name, ','.join(fields), self.primary_key, primary_key)
sql = sql.replace('?', '%s')
mysql.execute(sql, values)
four
通过元类,限制表名,主键数量,名称空间。
# orm.py
class Myorm(type):
def __new__(cls, class_name, class_base, class_attr):
if class_name == 'Model':
return type.__new__(cls, class_name, class_base, class_attr)
table_name = class_attr.get('table_name', class_name)
primary_key = False
mappings = {}
for k, v in class_attr.items():
if isinstance(v, Field):
mappings[k] = v
if v.primary_key:
if primary_key:
raise TypeError('只能有一个主键')
primary_key = v.name
for key in mappings.keys():
class_attr.pop(key)
if not primary_key:
raise TypeError('必须有一个主键')
class_attr['table_name'] = table_name
class_attr['primary_key'] = primary_key
class_attr['mappings'] = mappings
return type.__new__(cls, class_name, class_base, class_attr)
five
到此完事!!!