虽说廖老师python教程的实战已经过了一遍(除了部署以及编写移动App),但还是很多内容不理解,尤其是ORM框架。不过最近理解了使用元类里面一个精简的ORM框架,所以分享一下理解。
精简的ORM框架在这里,元类的介绍在这里。
分析源码
class User(Model):
id = IntegerField('id')
name = StringField('username')
email = StringField('email')
password = StringField('password')
u = User(id=12345, name='eyewater', email='test@orm.org', password='password')
u.save()
从User类的编写以及实例u的创建可以得到下面的信息
类属性分别为id,name,email,password
类属性对应的属性类型为
IntegerField,StringField,StringField,StringField
类属性对应的属性值为
12345,eyewater,test@orm.org,password
User类继承于Model类
class User(Model)
Model类的父类也是Model即为其本身(类的构造器)
def __init__(self, **kw):
super(Model, self).init__(**kw)
再来看ModelMetaclass
def __new__(cls, name, bases, attrs):
if name=='Model':
return type.__new__(cls, name, bases, attrs)
cls表示当前准备创建的类的对象即User类
name表示类名即User
bases表示类继承的父类集合
attrs代表类的属性集合即User类的属性集合id,name,email,password
for k, v in attrs.items():
if isinstance(v, Field):
print('Found mapping: %s ==> %s' % (k, v))
mappings[k] = v
k的值为id,name,email,password
v的值为IntegerField,StringField,StringField,StringField
所以看的输出就像这样:
Found mapping: email ==> <StringField:email>
Found mapping: password ==> <StringField:password>
Found mapping: id ==> <IntegerField:uid>
Found mapping: name ==> <StringField:username>
for k in mappings.keys():
attrs.pop(k)
删除属性,用属性__mappings__
来保存属性和列的映射
attrs['__table__'] = name
用属性__table__
来保存表名
回到Model类
def save(self):
fields = []
params = []
args = []
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))
getattr来获取属性值即12345,Michael,test@orm.org,my-pwd
所以输出看起来就像下面这样:
SQL: insert into User (id,username,email,password) values (?,?,?,?)
ARGS: [12345, 'eyewater', 'test@orm.org', 'password']