Python使用描述器实现ORM模型的方法详解

 更新时间:2022年02月14日 10:00:22   投稿:BJT  
这篇文章主要为大家详细介绍了Python描述器实现ORM模型,使用数据库,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

访问或者修改描述器对象的属性时无法触发__setattr__等方法,只会触发描述器类内部的__set__,__get__,__delete__方法.

ORM模型:类名对应表名,对象对应的数据行,类属性对应数据行的各字段,有几个表字段,就绑定几个类属性;往表中增加数据就是创建对象,每创建一个对象,就是增加一行数据记录。

ORM框架的功能:

1.建立模型类和表之间的对应关系,允许我们通过面向对象的方式操作数据库。

2.根据设计的模型类生成数据库中的表格。

3.通过方便的配置就可以进行数据库的切换。

MySql的常用数据类型:

1.整数:int,bit

2.小数:decimal(decimal表示浮点数,decimal(5,2)表示共计5位数,小数占2位)

3.字符串:varchar(可变长度),char(不可变长度)

4.日期时间:date,time,datetime

5.枚举类型:enum

模型类案例:

"""
django的ORM模型字段
BooleanField:   布尔字段,True或False
CharField(max_length=最大长度):     字符串,参数max_length表示最大字符个数
IntegerField:   整数
"""
class TestReport(BaseTable):
    class Meat:
        verbose_name = '测试报告'
        db_table = "TestReport"
    report_name = models.CharField(max_length=40, null=False)
    start_at = models.CharField(max_length=40, null=True)
    status = models.BooleanField()
    testRun = models.IntegerField()
    successes = models.IntegerField()
    reports = models.TextField()

1.__set__方法:设置属性 

"""
只要一个类中出现了:
    __get__(self,instance,owner)
    __set__(self,instance,value)
    __delete__(self,instance)
    __set_name__(self,owner,name)
    中的任意一个方法,这个类就不是一个普通的类了,
    应被称为:
        描述器类(应用在ORM模型中)
"""
class Field(object):
    """
    只要一个类中出现了以下任意一个方法,这个类就是一个描述器类
    """
    def __get__(self, instance, owner):
        pass
    def __set__(self, instance, value):
        print('---set---方法被触发了')
    def __delete__(self, instance):
        pass
class Model(object):
    attr = Field()  # attr是一个描述器对象,修改时无法触发__setattr__等方法,
                    # 只能触发描述器类内部的__set__方法
if __name__ == '__main__':
    m = Model()
    m.attr = 666    # 尝试修改attr属性
    print(m.attr)  
    # 输出:
    ---set - --方法被触发了
    None
 
class Field(object):
    """
    只要一个类中出现了以下任意一个方法,这个类就是一个描述器类
    """
    def __get__(self, instance, owner):
        pass
    def __set__(self, instance, value):
        """
        :param instance: 修改的对象
        :param value: 修改的值
        :return:
        """
        print('---set---方法被触发了')
        self.value = value
        print(self)      # <__main__.Field object at 0x7fecc01f8a30>
        print(instance)  # <__main__.Model object at 0x7fecc01f8a00>
        print(value)     # 666
    def __delete__(self, instance):
        pass
class Model(object):
    attr = Field()  # attr是一个描述器对象,修改时无法触发__setattr__等方法,
                    # 只能触发描述器类内部的__set__方法
if __name__ == '__main__':
    m = Model()
    print(m)      # <__main__.Model object at 0x7fecc01f8a00>,与instance相同
    m.attr = 666  # 尝试修改attr属性
 

2.__get__方法:访问属性

 
"""
只要一个类中出现了:
    __get__(self,instance,owner)
    __set__(self,instance,value)
    __delete__(self,instance)
    __set_name__(self,owner,name)
    中的任意一个方法,这个类就不是一个普通的类了,
    应被称为:
        描述器类(应用在ORM模型中)
"""
class Field(object):
    """
    只要一个类中出现了以下任意一个方法,这个类就是一个描述器类
    """
    def __get__(self, instance, owner):
        print('---get---方法被触发了')
    def __set__(self, instance, value):
        """
        :param instance: 修改的对象
        :param value: 修改的值
        :return:
        """
        print('---set---方法被触发了')
        self.value = value
    def __delete__(self, instance):
        pass
class Model(object):
    attr = Field()  # attr是一个描述器对象,修改时无法触发__setattr__等方法,
                    # 只能触发描述器类内部的__set__方法
if __name__ == '__main__':
    m = Model()
    m.attr = 666  # 尝试修改attr属性
    print(m.attr)
    # 输出:
    ---set - --方法被触发了
    ---get - --方法被触发了
    None
 
"""
只要一个类中出现了:
    __get__(self,instance,owner)
    __set__(self,instance,value)
    __delete__(self,instance)
    __set_name__(self,owner,name)
    中的任意一个方法,这个类就不是一个普通的类了,
    应被称为:
        描述器类(应用在ORM模型中)
"""
class Field(object):
    """
    只要一个类中出现了以下任意一个方法,这个类就是一个描述器类
    """
    def __get__(self, instance, owner):
        print('---get---方法被触发了')
        print(instance)     # <__main__.Model object at 0x7f80b81a09d0>
        print(owner)        # <class '__main__.Model'>
        return self.value
    def __set__(self, instance, value):
        """
        :param instance: 修改的对象
        :param value: 修改的值
        :return:
        """
        print('---set---方法被触发了')
        self.value = value
    def __delete__(self, instance):
        pass
class Model(object):
    attr = Field()  # attr是一个描述器对象,修改时无法触发__setattr__等方法,
                    # 只能触发描述器类内部的__set__方法
if __name__ == '__main__':
    m = Model()
    m.attr = 666  # 尝试修改attr属性
    print(m.attr)  # 666
    # 输出:
    ---set - --方法被触发了
    ---get - --方法被触发了
    < __main__.Model object at 0x7f80b81a09d0 >
    < class '__main__.Model'>
    666
 

3.__delete__方法:删除属性

"""
只要一个类中出现了:
    __get__(self,instance,owner)
    __set__(self,instance,value)
    __delete__(self,instance)
    __set_name__(self,owner,name)
    中的任意一个方法,这个类就不是一个普通的类了,
    应被称为:
        描述器类(应用在ORM模型中)
"""
class Field(object):
    """
    只要一个类中出现了以下任意一个方法,这个类就是一个描述器类
    """
    def __get__(self, instance, owner):
        return self.value
    def __set__(self, instance, value):
        """
        :param instance: 修改的对象
        :param value: 修改的值
        :return:
        """
        print('---set---方法被触发了')
        self.value = value
    def __delete__(self, instance):
        print('---delete---方法被触发了')
class Model(object):
    attr = Field()  # attr是一个描述器对象,修改时无法触发__setattr__等方法,
                    # 只能触发描述器类内部的__set__方法
if __name__ == '__main__':
    m = Model()
    m.attr = 666  # 尝试修改attr属性
    del m.attr    # ---delete---方法被触发了
    print(m.attr)  # None
    # 输出:
    ---set - --方法被触发了
    ---delete - --方法被触发了
    666
 
"""
只要一个类中出现了:
    __get__(self,instance,owner)
    __set__(self,instance,value)
    __delete__(self,instance)
    __set_name__(self,owner,name)
    中的任意一个方法,这个类就不是一个普通的类了,
    应被称为:
        描述器类(应用在ORM模型中)
"""
class Field(object):
    """
    只要一个类中出现了以下任意一个方法,这个类就是一个描述器类
    """
    def __get__(self, instance, owner):
        print('---get---方法被触发了')
        print(instance)     # <__main__.Model object at 0x7f80b81a09d0>
        print(owner)        # <class '__main__.Model'>
        return self.value
    def __set__(self, instance, value):
        """
        :param instance: 修改的对象
        :param value: 修改的值
        :return:
        """
        print('---set---方法被触发了')
        self.value = value
    def __delete__(self, instance):
        print('---delete---方法被触发了')
        print(instance)     # <__main__.Model object at 0x7ff61806a160>
        self.value = None
class Model(object):
    attr = Field()  # attr是一个描述器对象,修改时无法触发__setattr__等方法,
                    # 只能触发描述器类内部的__set__方法
if __name__ == '__main__':
    m = Model()
    m.attr = 666  # 尝试修改attr属性
    del m.attr    # ---delete---方法被触发了
    print(m.attr)  # None
    # 输出:
    ---set - --方法被触发了
    ---delete - --方法被触发了
    < __main__.Model object at 0x7ff61806a160 >
    ---get - --方法被触发了
    < __main__.Model object at 0x7ff61806a160 >
    <class '__main__.Model'>
    None
 

 4.描述器实现ORM模型: 

"""
通过描述器实现ORM模型
"""
class CharField(object):
    def __init__(self,max_length=20):
        self.max_length = max_length
    def __get__(self, instance, owner):
        return self.value
    def __set__(self, instance, value):
        # 首先判断是否为空
        if value is not None:
            # 再判断是否是字符串
            if isinstance(value, str):
                # 再判断长度是否符合要求
                if len(value) <= self.max_length:
                    self.value = value
                else:
                    raise TypeError('length need less than {}'.format(self.max_length))
            else:
                raise TypeError('need a str')
        else:
            raise TypeError("can not be None")
    def __delete__(self, instance):
        self.value = None
class IntegerField(object):
    def __get__(self, instance, owner):
        return self.value
    def __set__(self, instance, value):
        # 首先判断是否为空
        if value is not None:
            # 再判断是否是整数int
            if isinstance(value, int):
                self.value = value
            else:
                raise TypeError('need a int')
        else:
            raise TypeError("can not be None")
    def __delete__(self, instance):
        self.value = None
class UserModel(object):
    # 定义用户信息的模型类
    name = CharField(max_length=20)  # 定义:name只能赋值为字符串
    pwd = CharField(max_length=40)
    age = IntegerField()    # 定义:age只能赋值为整数
if __name__ == '__main__':
    user = UserModel()
    user.name = "春田"
    print(user.name)    # 输出: 春田
    user.age = 130
    print(user.age)  # 输出: 130
    user.pwd = 'wsdgdgdrgerdsfs方式范德萨发阿瑟费萨法 sfa fda fsdf sdf  fg'
    print(user.pwd)     # 输出: TypeError: length need less than 40
 

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注脚本之家的更多内容!  

相关文章

  • 详解Python如何解析JSON中的对象数组

    详解Python如何解析JSON中的对象数组

    这篇文章主要为大家详细介绍了如何使用Python的JSON模块传输和接收JSON数据,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2023-10-10
  • torchtext入门教程必看,带你轻松玩转文本数据处理

    torchtext入门教程必看,带你轻松玩转文本数据处理

    这篇文章主要介绍了torchtext入门教程必看,带你轻松玩转文本数据处理,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-05-05
  • python神经网络Batch Normalization底层原理详解

    python神经网络Batch Normalization底层原理详解

    这篇文章主要为大家介绍了python神经网络Batch Normalization底层原理详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-05-05
  • Django logging配置及使用详解

    Django logging配置及使用详解

    这篇文章主要介绍了Django logging配置及使用详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-07-07
  • python实现时间o(1)的最小栈的实例代码

    python实现时间o(1)的最小栈的实例代码

    这篇文章主要介绍了python实现时间o(1)的最小栈的实例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-07-07
  • 理解python多线程(python多线程简明教程)

    理解python多线程(python多线程简明教程)

    这篇文章主要介绍了理解python多线程,一个快速理解python多线程的简明教程,需要的朋友可以参考下
    2014-06-06
  • pycharm设置注释颜色的方法

    pycharm设置注释颜色的方法

    今天小编就为大家分享一篇pycharm设置注释颜色的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-05-05
  • Pycharm新建项目时报错解决办法

    Pycharm新建项目时报错解决办法

    pycharm可以很方便的管理Python的解释器(如果安装了多个的话),以及第三方模块,包,下面这篇文章主要给大家介绍了关于Pycharm新建项目时报错解决的相关资料,需要的朋友可以参考下
    2023-06-06
  • Python numpy二维数组如何删除指定行和列

    Python numpy二维数组如何删除指定行和列

    本文展示了如何对数组进行行列删除操作,包括删除单行、单列、多行和多列的方法,通过具体的运行结果展示,读者可以清晰地了解到如何在不同情况下进行数据处理,文章内容实用,适合需要进行数据处理的读者参考学习
    2024-09-09
  • 解读Python中字典的key都可以是什么

    解读Python中字典的key都可以是什么

    这篇文章主要介绍了解读Python中字典的key都可以是什么,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-09-09

最新评论