说一些自己对Python元类ORM的理解

最近在使用Django的一些功能时,不得不佩服Django这个框架的强大,真的很多功能或许你会使用,但是你有没有深层次的考虑他如何实现的?

ORM在Django中被使用的十分广泛,先介绍ORM是什么
ORM 是Object-Relation Mapping.缩写,即是关系映射

有了这个,你可以很轻松的完成数据库操作,设想一下,假如没有这个,你可能操作一次数据库需要使用pymysql连接,获取cursor,再写一个麻烦的SQL语句,再是execute,最后再关闭,一次已经很麻烦了,要是网站功能齐全,或许到处都需要用到MYSQL,那么你,一句一句写,可行的,但是,想想就很麻烦,更别提一个一个写了。

但是设想一下,要是通过创建一个类对象,你传进来值就能完成操作,是不是很有吸引力?

下面是我自己,查阅了很多资料,从大佬们那里理解到,画的一个示意图。

只需要这样对应,即可插入数据,看上去很轻松对吧?

2 元类

想要搞懂这个步骤,还需要理解一下元类。推荐看一下这位大佬的科普,很详细https://www.cnblogs.com/lyfstorm/p/11063460.html

其实看完这个,你应该会跟我当时一样有一个疑问,所有的类都是object的子类,而所有的类又都是从type创建的,type和object的关系是什么样子的?以及type以前我只是使用来查看数据类型的,居然还有这么逆天的功能?其实这些Google一下都有很详细的解释,这里不再赘述

3 一个简单的小例子,近似完成ORM关系映射的MYSQL插入

看下代码,很绕很绕,自己写的时候也被绕的差点出不来

class Django(type):
    def __new__(cls,name,parent,bonds):
        words = dict()
        for k,v in bonds.items():
            if isinstance(v,tuple):
                print("Found target %s ------>>%s"%(k,v))
                words[k]=v
        for k in words.keys():
            bonds.pop(k)
        bonds['__mappings__'] =words
        bonds["__table__"] = name
        return type.__new__(cls,name,parent,bonds)


class User(metaclass=Django):
    uid = ("id",'int unsigned')
    name = ('name','varchar(30)')
    email = ('email','varchar(30)')
    password = ('password','varchar(30)')
    #  创建类的时候使用Django方式创建,返回的对象里
    ## User就只有 __mappings__ 和__table__属性
    # __mapping__指向words字典,即原来的属性,
    ### __table__指向自己的类名
    def __init__(self,**kwargs):  # **kwargs是为了接受传进来的参数,
        for k,v in kwargs.items():
            setattr(self,k,v)
            """因为再这个地方,self.name = ...只会添加一个name属性,无法使用name的引用,
            因此只能使用setattr的方式添加self属性,再通过getattr的方式取得值"""
    def save(self):
        bond_name=list()
        bond_value=list()
        for k,v in self.__mappings__.items():
            """因为之前的属性都被保存在了这个mapping里,k为uid,name 等,v为mysql各个字段的名字(name,varchar(30)"""
            bond_name.append(v[0])
            bond_value.append(getattr(self,k,None))
        sql_language = "insert into %s(%s) values(%s);"%(self.__table__,','.join(bond_name),','.join(str(i) for i in bond_value))
        """这里只是举例使用mysql插入语句,insert into 表名(字段名) values(值);"""
        print(sql_language)

u=User(uid=1254,name="wang",email="oslo856852@qq.com",password="25480")
u.save()

运行结果如下

1 Found target uid ------>>('id', 'int unsigned')
2 Found target name ------>>('name', 'varchar(30)')
3 Found target email ------>>('email', 'varchar(30)')
4 Found target password ------>>('password', 'varchar(30)')
5 insert into User(id,name,email,password) values(1254,wang,oslo856852@qq.com,25480);
6 [Finished in 0.3s]
posted @ 2019-12-06 09:47  Oslo254804746  阅读(246)  评论(0)    收藏  举报