建设一个网站的一般过程,分析北师大教育学原理网站建设,wordpress全站加速,网销公司概述
什么是ORM? ORM全称“Object Relational Mapping”#xff0c;即对象-关系映射#xff0c;就是把关系数据库的一行映射为一个对象#xff0c;也就是一个类对应一个表#xff0c;这样#xff0c;写代码更简单#xff0c;不用直接操作SQL语句。 现在我们就要实…概述
什么是ORM? ORM全称“Object Relational Mapping”即对象-关系映射就是把关系数据库的一行映射为一个对象也就是一个类对应一个表这样写代码更简单不用直接操作SQL语句。 现在我们就要实现简易版ORM。 效果
class Person(Model):定义类的属性到列的映射pid IntegerField(id)names StringField(username)email StringField(email)password StringField(password)p Person(pid10086, names晓明, email10086163.com, password123456)
p.save() 通过执行save()方法 动态生成sql插入语句, 是不是很神奇 那我们现在开始解析原理吧 步骤 首先我们要定义一个 Field 类 它负责保存数据库表的字段名和字段类型
class Field(object):def __init__(self, name, column_type):self.name nameself.column_type column_typedef __str__(self):return %s:%s % (self.__class__.__name__, self.name) 在 Field 的基础上进一步定义各种类型的 Field比如 StringFieldIntegerField 等等
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) 下一步就是编写最复杂的 ModelMetaclass
class ModelMetaclass(type):def __new__(cls, name, bases, attrs):if name Model:return type.__new__(cls, name, bases, attrs)mappings dict()print(Found class: %s % name)for k, v in attrs.items():if isinstance(v, Field):print(Found mapping: %s %s % (k, v))mappings[k] vfor k in mappings.keys():attrs.pop(k)attrs[__table__] name # 表名和类名一致attrs[__mappings__] mappings # 保存属性和列的映射关系return type.__new__(cls, name, bases, attrs) 最后就是基类 Model:
class Model(metaclassModelMetaclass):def __init__(self, **kwargs):_setattr setattrif kwargs:for k, v in kwargs.items():_setattr(self, k, v)super(Model, self).__init__()def save(self):fields []params []args []for k, v in self.__mappings__.items():fields.append(k)params.append(?)args.append(getattr(self, k, None))sql insert into %s (%s) values (%s) % (self.__table__, ,.join(fields), ,.join(params))print(插入语句: %s % sql)print(参数: %s % str(args))def update(self):fields []args []for k, v in self.__mappings__.items():if getattr(self, k, None):fields.append(k?)args.append(getattr(self, k, None))sql update %s set %s % (self.__table__, ,.join(fields))print(更新语句: %s % sql)print(参数: %s % args)def filter(self, *args):passdef delete(self):pass 当用户定义一个 class Person(Model) 继承父类时Python解释器会在当前类 Person 的定义中找 __metaclass__如果没有找到就继续到父类中找 __metaclass__实在找不到就用默认 type 类。
我们在父类 Model 中定义了 __metaclass__ 的 ModelMetaclass 来创建 Person 类所以 metaclass 隐式地继承到子类。
在 ModelMetaclass 中一共做了几件事情 排除掉对 Model 类的修改 在当前类比如 Person 中查找定义的类的所有属性如果找到一个 Field 属性就把它保存到一个 __mappings__ 的dict中同时从类属性中删除该Field属性否则容易造成运行时错误 把表名保存到 __table__ 中这里简化为表名默认为类名。
在Model类中就可以定义各种操作数据库的方法比如save()delete()find()update() 等等。
我们实现了save(), update()方法把一个实例保存到数据库中。因为有表名属性到字段的映射和属性值的集合就可以构造出INSERT语句和UPDATE语句。 编写代码试试
class UserInfo(Model):定义类的属性到列的映射uid IntegerField(uid)name StringField(username)email StringField(email)password StringField(password)class Person(Model):定义类的属性到列的映射pid IntegerField(id)names StringField(username)email StringField(email)password StringField(password)p Person(pid10086, names晓明, email10086163.com, password123456)
p.save()
u2 UserInfo(password123456)
u2.update() 输出
Found class: UserInfo
Found mapping: uid IntegerField:uid
Found mapping: name StringField:username
Found mapping: email StringField:email
Found mapping: password StringField:password
Found class: Person
Found mapping: pid IntegerField:id
Found mapping: names StringField:username
Found mapping: email StringField:email
Found mapping: password StringField:password
插入语句: insert into Person (pid,names,email,password) values (?,?,?,?)
参数: [10086, 晓明, 10086163.com, 123456]
更新语句: update UserInfo set password?
参数: [123456] 结束语
就这样一个小巧的ORM就这么完成了。是不是学到了很多呢 这里利用的是元编程很多Python框架都运用了元编程达到动态操作类。
注上述代码列子 结合了廖雪峰的列子和少量的django ORM源码。 完整代码
class Field(object):def __init__(self, name, column_type):self.name nameself.column_type column_typedef __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)mappings dict()print(Found class: %s % name)for k, v in attrs.items():if isinstance(v, Field):print(Found mapping: %s %s % (k, v))mappings[k] vfor k in mappings.keys():attrs.pop(k)attrs[__table__] name # 表名和类名一致attrs[__mappings__] mappings # 保存属性和列的映射关系return type.__new__(cls, name, bases, attrs)class Model(metaclassModelMetaclass):def __init__(self, **kwargs):_setattr setattrif kwargs:for k, v in kwargs.items():_setattr(self, k, v)super(Model, self).__init__()def save(self):fields []params []args []for k, v in self.__mappings__.items():fields.append(k)params.append(?)args.append(getattr(self, k, None))sql insert into %s (%s) values (%s) % (self.__table__, ,.join(fields), ,.join(params))print(插入语句: %s % sql)print(参数: %s % str(args))def update(self):fields []args []for k, v in self.__mappings__.items():if getattr(self, k, None):fields.append(k?)args.append(getattr(self, k, None))sql update %s set %s % (self.__table__, ,.join(fields))print(更新语句: %s % sql)print(参数: %s % args)def filter(self, *args):passdef delete(self):passclass UserInfo(Model):定义类的属性到列的映射uid IntegerField(uid)name StringField(username)email StringField(email)password StringField(password)class Person(Model):定义类的属性到列的映射pid IntegerField(id)names StringField(username)email StringField(email)password StringField(password)p Person(pid10086, names晓明, email10086163.com, password123456)
p.save()
u2 UserInfo(password123456)
u2.update()