ORM:对象关系映射python
映射到数据库MySQL中的数据表数据库
类名——>表名app
对象——>一条记录code
对象.属性——>字段orm
模拟Django的ORM,是为了将对数据库中的增、删、改、查操做封装成一个个方式,方便调用对象
ORM处理的事情:get
一、控制表类的建立 ---> 控制表建立的过程; 二、给表类封装 增、查、改 方法it
# 定义字段类型:每个字段都应该有:字段名,字段类型,主键,默认值 # 字段父类 class Field: def __init__(self, name, column_type, primary_key, default): self.name = name self.column_type = column_type self.primary_key = primary_key self.default = default # 整型字段 class IntegerField(Field): # 字段类型默认是int,主键默认是False,默认值默认是0 def __init__(self, name, column_type='int', primary_key=False, default=0): super().__init__(name, column_type, primary_key, default) # 字符类型字段 class StringField(Field): # 字段类型默认是varchar,主键默认False,默认值是None def __init__(self, name, column_type='varchar(64)', primary_key=False, default=None): super().__init__(name, column_type, primary_key, default) # 自定义元类:解决三件事: # 一、保证一张表必须有一个表名 # 二、一张表有且只有一个主键 # 三、将全部的 “ 字段名” 和 “字段对象” 添加到一个名称空间中,方便调用(mapping) class OrmMetaClass(type): # 由__call__ 产生 __new__ ,定义类就会触发__new__,从新__new__对定义的类进行限制 def __new__(cls, class_name, class_bases, class_dict): # 不要限制父类Models,过滤掉父类 if class_name == 'Models': return type.__new__(cls, class_name, class_bases, class_dict) # 获取table 表名,若是没有,设置默认值为类名 table_name = class_dict.get('table_name', class_name) # 设置主键变量初始值为None primary_key = None # 设置一个空字典用来存放字段和字段对象 mapping = {} # 循环取值名称空间中的key和value for key, value in class_dict.items(): # 判断当前的value是不是字段对象 if isinstance(value, Field): # 将全部的字段和字段对象加入空字典中 mapping[key] = value # 判断是否有主键,若是有,将primary_key变量赋值 if value.primary_key: # 第二次进来,若是有主键了,抛出异常 if primary_key: raise TypeError('只能有一个主键!!!') primary_key = value.primary_key # 过滤掉重复的字段属性,节省空间 for key in mapping.keys(): class_dict.pop(key) # 判断 是否有主键,若是没有,抛出异常 if not primary_key: raise TypeError('必需要有一个主键!!!') # 给类的名称空间中加入table_name, primary_key, mapping class_dict['table_name'] = table_name class_dict['primary_key'] = primary_key class_dict['mapping'] = mapping # 将限制操做后的__new__返回 return type.__new__(cls, class_name, class_bases, class_dict) # 定义父类 class Models(dict,metaclass=OrmMetaClass): # 经过对象.属性的方式获取值时,属性没有时调用 def __getattr__(self, item): return self.get(item) # 设置对象.属性 = 属性值 时触发 def __setattr__(self, key, value): self[key] = value class User(Models): # 字段类中的name属性,必需要与User表中类属性同名 id = IntegerField(name='id', primary_key=True) username = StringField(name='username') password = StringField(name='password')