ORM

ORM

ORM(ObjectRelationMapping):对象关系映射

映射到数据库MySQL中的数据表

类名——>表名

对象——>一条记录

对象.属性——>字段

模拟Django的ORM,是为了将对数据库中的增、删、改、查操作封装成一个个方式,方便调用

ORM处理的事情:

​ 1、控制表类的创建 ---> 控制表创建的过程; 2、给表类封装 增、查、改 方法

# 定义字段类型:每一个字段都应该有:字段名,字段类型,主键,默认值
# 字段父类
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)


# 自定义元类:解决三件事:
# 1、保证一张表必须有一个表名
# 2、一张表有且只有一个主键
# 3、将所有的 “ 字段名” 和 “字段对象” 添加到一个名称空间中,方便调用(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')
posted @ 2019-12-18 23:06  Mr沈  阅读(524)  评论(0编辑  收藏  举报