zoukankan      html  css  js  c++  java
  • Python实现一个ORM模型类

    ORM是三个单词首字母组合而成,包含了Object(对象-类),Relations(关系),Mapping(映射)。解释过字面意思,但ORM的概念仍然模糊。私以为要理解一个事物,最好的法子是搞明白它出现是为了解决什么问题。

    一个简单的ORM模型

    我们也可以通过元类来实现自己的ORM。下面将涉及两个知识点:元类,描述符。

    首先完成属性描述符的设计:

    class BaseFiled(object):
        pass
    
    
    class CharFiled(BaseFiled):
        def __init__(self, max_len=10):
            self.max_len = max_len
    
        def __get__(self, instance, owner):
            return self.value
    
        def __set__(self, instance, value):
            if isinstance(value, str):
                # 判断类型进行控制
                if len(value) <= self.max_len:
                    self.value = value
                else:
                    raise TypeError('超出最大长度')
            else:
                raise TypeError('need a str')
    
        def __delete__(self, instance):
            self.value = None
    
    
    class IntFiled(BaseFiled):
        def __init__(self, max_len=10):
            self.max_len = max_len
    
        def __get__(self, instance, owner):
            return self.value
    
        def __set__(self, instance, value):
            if isinstance(value, int):
                # 判断类型进行控制
                if len(str(value)) <= self.max_len:
                    self.value = value
                else:
                    raise TypeError('超出最大长度')
            else:
                raise TypeError('need a int')
    
        def __delete__(self, instance):
            self.value = None
    
    
    class BoolFiled(BaseFiled):
        def __init__(self, max_len=10):
            self.max_len = max_len
    
        def __get__(self, instance, owner):
            return self.value
    
        def __set__(self, instance, value):
            if isinstance(value, bool):
                # 判断类型进行控制
                self.value = value
            else:
                raise TypeError('need a bool')

    实现一个元类:

    class FieldMetaClass(type):
        # 创建模型类的元类
        def __new__(cls, name, bases, dic, *args, **kwargs):
            if name == 'BaseModel':
                return super().__new__(cls, name, bases, dic)
            table_name = name.lower()
            # 将类名转换成小写,对应数据表的名称
            fields = {}
            for k, v in dic.items():
                # 判断value的类型是不是BaseFiled类型的 因为调用的类的父类就是BaseFiled 所以通过CharFiled等创建出来的对象也就是BaseFiled类型的
                if isinstance(v, BaseFiled):
                    fields[k] = v
            dic['t_name'] = table_name
            dic['fields'] = fields
            # 将类名和属性取出来放在一个字典中
            return super().__new__(cls, name, bases, dic)

    给模型类创建一个父类,具体原因及作用可以观察注释:

    class BaseModel(metaclass=FieldMetaClass):
        # 模型类的父类
        def __init__(self, **kwargs):
            # kwargs 传入的是一个字典
            for k, v in kwargs.items():
                setattr(self, k, v)
                # setattr 设置属性  传入对象、属性名、属性值
    
        def save(self):
            # 保存一条数据,生成一条对应的sql语句
            # 获取表名
            t_name = self.t_name
            # 获取字段名称
            fields = self.fields
            # 获取对应字段的值
            filed_dict = {} # 创建一个字典用来存储键值对
            for filed in fields.keys():
                value = getattr(self, filed)
                # 把遍历出来的键中的值找到
                filed_dict[filed] = value
    
            # 生成对应的sql语句
            sql = 'INSERT INTO {0} VALUES {1};'.format(t_name, tuple(filed_dict.values()))
           

    生成模型类:

    class User(BaseModel):
        # 用户模型类 在模型类中不会重写init方法,在它的父类中写init方法 它会自动继承
        username = CharFiled()
        pwd = CharFiled()
        age = IntFiled()
        live = BoolFiled()

    调用方式:

    a = User(username='12', pwd='19', age=20, live=True)
    a.save()

    这样就实现了一个模型类,注释写的个人感觉还是比较清晰的,有不清楚的欢迎留言交流

  • 相关阅读:
    Vijos P1597 2的幂次方【进制+递归】
    NUC1100 Biorhythms【中国剩余定理】
    HDU1370 Biorhythms【中国剩余定理】
    NUC1090 Goldbach's Conjecture【哥德巴赫猜想 】
    NUC1305 哥德巴赫猜想
    剑指Offer——最小的K个数
    剑指Offer——数组中出现次数超过一半的数字
    剑指Offer——字符串的排列
    剑指Offer——二叉搜索树与双向链表
    剑指Offer——复杂链表的复制
  • 原文地址:https://www.cnblogs.com/congyiwei/p/12578245.html
Copyright © 2011-2022 走看看