Django核心:元类与orm对象关系映射

元类

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

猜你喜欢

转载自blog.csdn.net/qq_34788903/article/details/84935830