• 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()

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

  • 相关阅读:
    面向接口程序设计思想实践
    Block Chain Learning Notes
    ECMAScript 6.0
    Etcd Learning Notes
    Travis CI Build Continuous Integration
    Markdown Learning Notes
    SPRING MICROSERVICES IN ACTION
    Java Interview Questions Summary
    Node.js Learning Notes
    Apache Thrift Learning Notes
  • 原文地址:https://www.cnblogs.com/congyiwei/p/12578245.html
Copyright © 2020-2023  润新知