基于元类实现ORM
程序员文章站
2022-05-31 23:29:22
...
"""
基于元类,实现ORM--模拟django
"""
# Field定义字段基类,包括字段名字和字段类型
class Field(object):
def __init__(self, name, column_type):
self.name = name
self.column_type = column_type
# 定义可读性更好的__str__()
def __str__(self):
return f'<{self.__class__.__name__}: {self.name}>'
# 定义charField类
class CharField(Field):
def __init__(self, name, max_length):
super().__init__(name, f'varchar({max_length})')
# 定义Integer类
class IntegerField(Field):
def __init__(self, name):
super().__init__(name, 'int')
# 定义模型基类
class ModelMeta(type):
# attrs 是字典对象
def __new__(cls, name, bases, attrs):# 查看这个attr的键值对
if name == 'Model':
return type.__new__(cls, name, bases, attrs)
print('Model name : ', name)# 会自动传送类名过来
mappings = dict()
for k, v in attrs.items():
if isinstance(v, Field):
print('Field Mapping',(k, v))
mappings[k] = v
# 便利mappings 将字典attrs中的键删掉
for k in mappings:
attrs.pop(k)
attrs['__mappings__'] = mappings
attrs['__table__'] = name
return type.__new__(cls, name, bases, attrs)
class Model(dict, metaclass=ModelMeta):
def __init__(self, **kwargs):
super().__init__(**kwargs)
def __getattr__(self, key):
try:
return self[key]
except:
raise AttributeError(f'Model not {key} key')
def __setattr__(self, key, value):
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, args)
class Person(Model):
id = IntegerField(name='pid')
name = CharField('pname', max_length=20)
age = IntegerField('age')
if __name__ == '__main__':
p = Person(id=1, name='disen', age=20)
p.save()
Q&A
- args.append(getattr(self, k, None))为啥能够获得用户输入的值,而不是类变量
- for k, v in self.mappings.items():此处字典__mappings__中的键值对则是变成如下图中的Field Mapping括号中所示
- 对1,2 两点的猜测,涉及到类变量和实例变量getattr()得到的是当前实例变量的属性,而底层(父类)得到的则是类变量