Django核心:元類與orm物件關係對映
阿新 • • 發佈:2018-12-13
元類
python中所有東西都是物件,包括類也是物件,建立類的類就叫做元類,參考文章深刻理解元類
一個例項
def upper_attr(class_name,class_parents,class_attr):
new_attr={}
for name,value in class_attr.items():
if not name.startswith("__"):
new_attr[name.upper()]=value
return type(class_name,class_parents,new_attr)
class Foo(object,metaclass=upper_attr):
bar="bip"
print(hasattr(Foo,"bar"))
print(hasattr(Foo,"BAR"))
f=Foo()
print(f.BAR)
建立一個類的時候如果沒有metaclass引數,就直接用type建立類,但是有了這個引數之後,去到這個函式引用,把類名Foo傳遞給class_name,把object傳遞給class_parents,把其他類屬性傳遞給class_attr。返回type(class_name,class_parents,class_attr)
面向物件改造
class UpperAttrMetaClass(type):
def __new__(cls, class_name,class_parents,class_attr):
new_attr={}
for name,value in class_attr.items():
if not name.startswith("__"):
new_attr[name.upper()]=value
return type(class_name,class_parents,new_attr)
class Foo(object,metaclass=UpperAttrMetaClass):#指定一個元類
bar="bip"
print(hasattr(Foo,"bar"))
print(hasattr(Foo,"BAR"))
f=Foo()
print(f.BAR)
以上程式碼實現的是將建立類的屬性都變成大寫
orm本質
其本質是通過呼叫物件實現同等的sql語句
- ex:insert into 表 欄位列表 value 欄位值列表==> u=user(字典) u.save()
orm實現
class ModelMetaClass(type):
def __new__(cls, name, bases, attrs):
mappings = dict()
for k, v in attrs.items():
if isinstance(v, tuple):
mappings[k] = v
for k in mappings.keys():
attrs.pop(k)
attrs['__mappings__'] = mappings
attrs['__table__'] = name
return type.__new__(cls,name,bases,attrs)
class User(metaclass=ModelMetaClass):
uid=('uid',"int unsigned")
name=('username',"barchar(30)")
email=('email',"varchar(30)")
password=('password',"varchar(30)")
def __init__(self,**kwargs):
for name,value in kwargs.items():
setattr(self,name,value)
def save(self):
fields=[]
args=[]
for k,v in self.__mappings__.items():
fields.append(v[0])
args.append(getattr(self,k,None))
args_temp=list()
for temp in args:
if isinstance(temp,int):
args_temp.append(str(temp))
elif isinstance(temp,str):
args_temp.append("""'%s'"""%temp)
sql='insert into %s (%s) values (%s)'%(self.__table__,','.join(fields),\
','.join(str(i) for i in args_temp))
print(sql)
u=User(uid=122,name="zhangyue",email="xxx",password="pass")
u.save()
思想:
用元類來建立User類,uid、name、email、password等屬性。傳遞到元類,元類接受之後把他們轉換成字典,用__mappings__儲存,表明也就是User用__table__儲存,用pop刪除原來的屬性,使字典為新的屬性,這樣做的目的是為了匹配sql語句的表名,和欄位名
#執行結果
author:specyue@mail.ustc.edu.cn
github:https://github.com/zhangyuespec/mini_web