1 #! /usr/bin/env python3 2 #-*- coding:utf-8 -*- 3 4 5 class Field(object): 6 def __init__(self, name, column_type): 7 self.name = name 8 self.column_type = column_type 9 10 def __str__(self): 11 return '<%s:%s>' % (self.__class__.__name__,self.name) 12 13 class StringField(Field): 14 15 def __init__(self, name): 16 super(StringField, self).__init__(name,'varchar(100)') 17 18 class IntegerField(Field): 19 20 def __init__(self, name): 21 super(IntegerField, self).__init__(name,'bigint') 22 23 class ModelMetaclass(type): 24 25 def __new__(cls,name,bases,attrs): 26 if name=='Model': 27 return type.__new__(cls,name,bases,attrs) 28 29 print('Found model:%s'%name) 30 mappings = dict() 31 # 将属性放入mappings中 32 for k,v in attrs.items(): 33 # 判断属性类型 34 if isinstance(v,Field): 35 print('Found mapping:%s==>%s'%(k,v)) 36 mappings[k]=v 37 # 移除原有的属性 38 for k in mappings.keys(): 39 attrs.pop(k) 40 # 新建__mappings__并将mappings赋值给它。将类名赋值给__table__ 41 attrs['__mappings__']=mappings 42 attrs['__table__']= name 43 return type.__new__(cls,name,bases,attrs) 44 45 class Model(dict,metaclass=ModelMetaclass): 46 47 def __init__(self, **kw): 48 super(Model, self).__init__(**kw) 49 50 def __getattr__(self,key): 51 try: 52 return self[key] 53 except KeyError: 54 raise AttributeError(r"'Model' object has no attribute '%s'"%key) 55 56 def __setattr__(self,key,value): 57 self[key]= value 58 59 def save(self): 60 fields = [] 61 params = [] 62 args = [] 63 # 将__mappings__转换为SQL语句。并将数值放入Args中 64 for k,v in self.__mappings__.items(): 65 fields.append(v.name) 66 params.append('?') 67 args.append(getattr(self,k,None)) 68 sql = 'insert into %s(%s) values(%s)'%(self.__table__,','.join(fields),','.join(params)) 69 print('SQL:%s'%sql) 70 print('ARGS:%s'%str(args)) 71 72 class User(Model): 73 # 定义类的属性到列的映射: 74 id = IntegerField('id') 75 name = StringField('username') 76 email = StringField('email') 77 password = StringField('password') 78 79 # 创建一个实例: 80 u = User(id=12345, name='Michael', email='test@orm.org', password='my-pwd') 81 # 保存到数据库: 82 u.save()
- 使用了类集成
- 使用了元类(本质是一个类的模版,在新建时对类的属性进行处理)
输出结果
1 Found model:User 2 Found mapping:email==><StringField:email> 3 Found mapping:name==><StringField:username> 4 Found mapping:password==><StringField:password> 5 Found mapping:id==><IntegerField:id> 6 SQL:insert into User(password,username,email,id) values(?,?,?,?) 7 ARGS:['my-pwd', 'Michael', 'test@orm.org', 12345]