# 把所有 '類別變數,函式' 進行處理
# 與instance變數(self.xxx)無關
class TestMetaclass(type):
def __new__(cls, name, bases, attrs):
# cls : 當前的類別
# name : 當前類別的名稱
# bases : 當前類別的父類別
# attrs : 產生instance當下的所有 '類別' 變數 與 方法
mappings = dict()
for k, v in attrs.items():
## 也可用hasattr(v, '__call__')或callable(v) 來過濾是否為function,如是function會回傳True
if isinstance(v, <some of object type>):
mappings[k] = v
# 將所有類別變數移除,並用 __mappings__ 這個變數指到變數字典(ex.{'x1':'1','x2':'2'})
# 之後在處理時,就loop __mappings__.items() 取key 跟 value
for k in mappings.keys():
attrs.pop(k)
attrs['__mappings__'] = mappings
attrs['__table__'] = name
return type.__new__(cls, name, bases, attrs)
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 StringField(Field):
def __init__(self, name):
super(StringField, self).__init__(name, 'varchar(100)')
class IntegerField(Field):
def __init__(self, name):
super(IntegerField, self).__init__(name, 'bigint')
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
#print(attrs)
for k in mappings.keys():
attrs.pop(k)
attrs['__mappings__'] = mappings # 保存属性和列的映射关系
attrs['__table__'] = name # 假设表名和类名一致
#print(attrs)
return type.__new__(cls, name, bases, attrs)
class Model(dict, metaclass=ModelMetaclass):
def __init__(self, **kw):
super(Model, self).__init__(**kw)
# 因繼承dict,所以用(k=v,k=v)會轉成{'k':v,'k':v}
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):
self[key] = value
print('{}:{}'.format(key,value))
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)) # 比較定義值與__setattr__(self, key, value) 產生出來的值
sql = 'insert into %s (%s) values (%s)' % (self.__table__, ','.join(fields), ','.join(params))
print('SQL: %s' % sql)
print('ARGS: %s' % str(args))
class User(Model):
# 定义类的属性到列的映射:
# 即定義有用的欄位
id = IntegerField('id')
name = StringField('username')
email = StringField('email')
password = StringField('password')
u = User(id=12345, name='Michael', email='[email protected]', password='my-pwd')
# 因繼承dict,所以用(k=v,k=v)會轉成{'k':v,'k':v}
# 這些初始值設定跟User定義的id,name,email,password無關