说一些自己对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]

浙公网安备 33010602011771号