ORM: Object Relational Mapping---对象关系映射
类名---表名, 一个对象的某个属性值---某个记录, 一个对象的属性值---一条记录, 对象.属性---字段
- 存储对象 --> dict --> Json --> Mysql
- Mysql --> Jason --> dict --> 获取对象
- 一个对象中的所有属性名和属性值映射成一个字典中的keys和values
- 将映射字典序列化成json格式
- 将json格式数据编码传输到服务器
- 在服务器将二进制数据解码并反序列化存入mysql数据库中
自定义元类
''' 自定义元类: 继承type类, 重写__new__方法, 控制类在创建时自动对类的名称空间中的属性进行相应的操作, 包括: 1. 一个表类的名称空间中必须要有一个表名的属性---模型表类除外 2. 一个表类的名称空间中的所有字段属性中, 必须有且仅有一个字段的主键为True 3. 将一个表类的名称空间中的所有字段属性放入一个独立字典中, 与名称空间中的其他属性区分开, 从而方便获取字段属性的属性名, 因其与字段对象中的字段名同名, 故等价于方便了字段名的获取 ''' # 自定义元类 class OrmMeta(type): # 参数"mcs"为自定义的元类, 由"msc"来创建一个空类 def __new__(mcs, cls_name, cls_bases, cls_dic): # 过滤掉"TableModel"类, 将其正常创建 if cls_name == 'TableModel': return type.__new__(mcs, cls_name, cls_bases, cls_dic) # 保证一个表必定有一个表名 table_name = cls_dic.get('table_name') if not table_name: cls_dic['table_name'] = cls_name # 定义一个字典存储一个表类中的所有字段对象 field_obj_dic = {} # 保证有且仅有一个主键 count = 0 for key, value in cls_dic.items(): # 遍历表类的名称空间 if isinstance(value, FieldBase): # 过滤掉非字段对象的数据 field_obj_dic[key] = value # 添加字段对象至字典 if value.primary_key: # 判断主键是否存在 primary_key_name = key # 记录主键的字段名 count += 1 # 对主键总数计数 if count > 1: raise TypeError('只能有一个主键值!') # 主键个数大于1报错 if count == 0: key = list(field_obj_dic)[0] primary_key_name = field_obj_dic.get(key).field_name # 没有主键默认将第一个字段名设为主键 # 剔除类的名称空间中的字段对象数据, 节省内存空间 for key in field_obj_dic.keys(): cls_dic.pop(key) # 给类的名称空间添加主键 cls_dic['primary_key_name'] = primary_key_name # 给类的名称空间添加包含一个表中的所有字段对象的字典 cls_dic['field_obj_dic'] = field_obj_dic return type.__new__(mcs, cls_name, cls_bases, cls_dic)
定义表模型类
# 定义表模型类 class TableModel(dict, metaclass=OrmMeta): # 通过"对象.属性名 = 属性值"的方式往字典对象中存储数据 def __setattr__(self, key, value): self[key] = value # 通过"对象.属性名"的方式从字典对象中获取数据 def __getattr__(self, item): return self.get(item) # 创建用户表类, 每个字段属性组合对应的字段对象 class UserTable(TableModel): # 表名 table_name = 'user_info' # 每个字段属性 user_id = IntegerField('user_id', primary_key=True) user_name = StringField('user_name') user_pwd = StringField('user_pwd') # 创建电影表类 class MovieTable(TableModel): movie_id = IntegerField('movie_id', primary_key=True) movie_name = StringField('movie_name') movie_pwd = StringField('movie_pwd') user1 = UserTable(user_id=1, user_name='tank', user_pwd='123') print(UserTable.__dict__)