首先见代码:
#!/usr/bin/env python3
# encoding: utf-8
# @File: __init__.py.py
# @Author : Leon Chu <leon_chu@apple.com>
# @Time : 2019-03-15 15:45
class Field(object):
def __init__(self, name, column_type):
self.name = name
self.column_type = column_type
def __str__(self,):
return "<%s:%s>" % (self.__class__.__name__, self.name)
class IntegerField(Field):
def __init__(self, name):
super(IntegerField, self).__init__(name, "bigint")
class StringField(Field):
def __init__(self, name):
super(StringField, self).__init__(name, "varchar(20)")
class ModelMetaclass(type):
def __new__(mcs, name, bases, attrs):
if name == "Model":
return type.__new__(mcs, name, bases, attrs)
print("Found Model:%s" % name)
mappings = dict() # 将类定义的属性保存到dict
for k, v in attrs.items():
# 如果有定义的属性
if isinstance(v, Field):
print("Found mappings:%s --> %s" % (k, v))
mappings[k] = v
for k in mappings.keys():
attrs.pop(k)
attrs['__mappings__'] = mappings # 保存属性和列的映射关系
attrs['__table__'] = name # 假设表名和类名一致
res = type.__new__(mcs, name, bases, attrs)
print(res.__dict__)
return res
class Model(dict, metaclass=ModelMetaclass):
# 这里还不是特别清楚
def __init__(self, **kw):
super(Model, self).__init__(**kw)
def __getattr__(self, key): # 属性校验
try:
return self[key]
except KeyError:
raise AttributeError(r"'Model' object has no attribute '%s'" % key)
def __setattr__(self, key, value): # set
self[key] = value
def save(self): # 保存
fields = []
params = []
args = []
# 这里通过__mappings__拿到了子类的属性
for k, v in self.__mappings__.items():
fields.append(v.name)
params.append('?')
args.append(getattr(self, k, None))
# 连接数据库驱动即可真正连接
sql = "insert into %s (%s) values (%s)" % (self.__table__, ','.join(fields), ','.join(params))
print('SQL: %s' % sql)
print('ARGS: %s' % str(args))
def delete(self): # 删
# 连接数据库驱动即可真正连接
sql = "delete from %s" % self.__table__
print('SQL: %s' % sql)
def update(self): # 改
fields = []
params = []
args = []
for k, v in self.__mappings__.items():
fields.append(v.name)
params.append('?')
args.append(getattr(self, k, None))
# 连接数据库驱动即可真正连接
sql = "update %s set %s=%s" % (self.__table__, ','.join(fields), ','.join(params))
print('SQL: %s' % sql)
print('ARGS: %s' % str(args))
def find(self): # 查
# 连接数据库驱动即可真正连接
sql = "select * from %s" % self.__table__
print('SQL: %s' % sql)
class User(Model):
id = IntegerField("id")
username = StringField("username")
password = StringField("password")
email = StringField("email")
if __name__ == '__main__':
u = User()
u.id = 1
u.save()
接下来一步步解析
首先 我们如果要编写orm框架,想到的一定是学一个牛逼的父类,活都扔给他干,然后用子类继承他,以获得他的能力
这里 Model 就是这个父类
接下来的问题是如何让父类具有这个能力,即操作数据库的能力,这个不难,而难的是他需要把这些能力都传递给继承他的类
本例子中;即 ModelMetaclass
他做了几件事情
在ModelMetaclass中,一共做了几件事情:
一,排除掉对Model类的修改;
二,在当前类(比如User)中查找定义的类的所有属性,如果找到一个Field属性,就把它保存到一个__mappings__的dict中,同时从类属性中删除该Field属性,否则,容易造成运行时错误(实例的属性会遮盖类的同名属性);
三,把表名保存到__table__中,这里简化为表名默认为类名。
即做到了在父类中操作子类