https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/0014319106919344c4ef8b1e04c48778bb45796e0335839000
http://blog.jobbole.com/21351/
https://stackoverflow.com/questions/100003/what-is-a-metaclass-in-python
个人理解:
DAG: dict <- Model <- User (ModelMetaclass(type)作用于User类的创建)
执行过程:用metaclass创建User类,再创建实例u
1、类的创建:dict <- Model <- User (ModelMetaclass(type)作用于User类的创建)
Model类按默认创建,ModelMetaclass(type)作用于User类的创建:
class ModelMetaclass(type):
def __new__(cls, name, bases, attrs):
if name=='Model':
return type.__new__(cls, name, bases, attrs)
print('Found model: %s' % name)
mappings = dict()
for k, v in attrs.items():
if isinstance(v, Field):
print('Found mapping: %s ==> %s' % (k, v))
mappings[k] = v
for k in mappings.keys():
attrs.pop(k)
attrs['__mappings__'] = mappings # 保存属性和列的映射关系
attrs['__table__'] = name # 假设表名和类名一致
return type.__new__(cls, name, bases, attrs)
在创建User类时,中name == User, bases == Model, attrs 是即将创建的类 User的类属性
(type(类名, 父类的元组(针对继承的情况,可以为空),包含属性的字典(名称和值))
|
元类会自动将你通常传给‘type’的参数作为自己的参数传入
|
class User(Model):
# 定义类的属性到列的映射:
id = IntegerField('id')
name = StringField('username')
email = StringField('email')
password = StringField('password')
那么for k, v in attrs.items()中,k 为'id'等(赋值号左边),'v'为IntegerField('id')实例等(赋值号右边);
在当前类(比如User)中查找定义的类的所有属性,如果找到一个Field属性,就把它保存到一个__mappings__的dict中,同时从类属性中删除该Field属性,否则,容易造成运行时错误(实例的属性会遮盖类的同名属性)详见:实力属性和类属性 https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/0014319117128404c7dd0cf0e3c4d88acc8fe4d2c163625000
Output:
Found model: User
Found mapping: email ==>
Found mapping: password ==>
Found mapping: id ==>
Found mapping: name ==>
2、u = User(..........)
u有类属性attrs['__mappings__'] = mappings, 同时u也是一个dict实例,{'id':12345, 'name':'Michael', ........................}
u.save()
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))
Output:
SQL: insert into User (password,email,username,id) values (?,?,?,?)
ARGS: ['my-pwd', '[email protected]', 'Michael', 12345]
k 与 v 在__mappings__.items()中分别为key 和 value(类型为Field)
k 在 self 即{'id':12345, 'name':'Michael', ........................}(类型为User,继承自dict)中为key, 当k为'id'时,返回12345
id = IntegerField('id') 右边是列(表头名),左边是相应的类属性(作为k)
u = User(id=12345, name='Michael', email='[email protected]', password='my-pwd') 也就是字典 {'id':12345, 'name':'Michael', 'email': '[email protected]', 'password': 'my-pwd'} ,是要插入的行数据,其中id是类属性(作为k)