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

目录
  • 1.__set__方法:设置属性
  • 2.__get__方法:访问属性
  • 3.__delete__方法:删除属性
  • 4.描述器实现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
 

总结

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

(0)

相关推荐

  • Python Django ORM与模型详解

    目录 一. 环境准备: 1.docker环境 docker环境如下: 2.安装mariadb数据库 运行如下命令: docker run -d --name [容器名称] -v test:/var/lib/mysql -p 3306:3306 --env MARIADB_USER=[用户名] --env MARIADB_PASSWORD=[用户密码] --env MARIADB_ROOT_PASSWORD=[root用户密码] --env MARIADB_DATABASE=[库名] mariad

  • 如何使用Python实现一个简易的ORM模型

    本文记录下自己使用Python实现一个简易的ORM模型 使用到的知识 1.元类 2.描述器 元类 对于元类,我的理解其实也便较浅,大概是这个意思 所有的类都是使用元类来进行创建的,而所有的类的父类中必然是object(针对Python3),Python中的元类只有一个(type),当然这里不包含自定义元类 下面我们来看下类的创建 class Test: # 定义一个类 pass Test1 = type("Test2",(object,),{"name":"

  • python利用元类和描述器实现ORM模型的详细步骤

    ORM模型: ORM模型对于后端开发来说肯定是不陌生的,包括很多后端框架比如django,现在都自带这个模型了 ORM(Object Relational Mapping)对象关系映射 Python中的类与数据库之间的映射,对数据的操作就不用编写SQL语言了,因为都封装好了,比如你想插入一条数据,你就直接创建一个对象即可, 类名 ------->>>> 数据库中的表名 属性 ------->>>> 数据库中的字段 对象 ------->>>

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

    目录 1.__set__方法:设置属性 2.__get__方法:访问属性 3.__delete__方法:删除属性 4.描述器实现ORM模型: 总结 访问或者修改描述器对象的属性时无法触发__setattr__等方法,只会触发描述器类内部的__set__,__get__,__delete__方法. ORM模型:类名对应表名,对象对应的数据行,类属性对应数据行的各字段,有几个表字段,就绑定几个类属性:往表中增加数据就是创建对象,每创建一个对象,就是增加一行数据记录. ORM框架的功能: 1.建立模型

  • Python argparse模块实现解析命令行参数方法详解

    argparse是Python的一个标准模块,用于解析命令行参数,即解析sys.argv中定义的参数.实现在:传送门 argparse模块还会自动生成帮助和使用信息,即在最后加-h或--help.当用户输入的参数无效时,会触发error,并给出出错原因. python test_argparse.py -h python test_argparse.py --help 使用argparse的步骤: 1.创建解析器:argparse.ArgumentParser(),ArgumentParser是

  • 把Dapper 换成 SqlSugar ORM类的方法详解

    目录 为什么要写这篇文章 Dapper 介绍 SqlSugar 介绍 性能对比 移植教程 为什么要写这篇文章 因数我看到很多人虽然用着SqlSugar,但是同时也用着Dapper,因为SqlSugar兼容了Dapper所有API,所以既然你用了SqlSugar那么就没有必要在同一个项目中使用2个ORM 所以这篇文章是给使用SqlSugar或者你想使用SqlSugar的朋友看的 Dapper 介绍 Dapper是一个轻量级开源的ORM类,他是通过扩展IDbConnection提供一些有用的扩展方法

  • Python中提取人脸特征的三种方法详解

    目录 1.直接使用dlib 2.使用深度学习方法查找人脸,dlib提取特征 3.使用insightface提取人脸特征 安装InsightFace 提取特征 1.直接使用dlib 安装dlib方法: Win10安装dlib GPU过程详解 思路: 1.使用dlib.get_frontal_face_detector()方法检测人脸的位置. 2.使用 dlib.shape_predictor()方法得到人脸的关键点. 3.使用dlib.face_recognition_model_v1()方法提取

  • 利用Python上传日志并监控告警的方法详解

    目录 1.准备 2.使用阿里云SDK上传Python日志 3.配置日志告警 在我们的日常生活工作中,经常会遇到需要上传日志的场景,比如多台机器运行同一个程序,并且需要记录每台机器程序产生的日志,根据相关关键词告警,或者进行无数据告警,如果自己搭建这套系统需要耗费不少时间,因此如果能使用市面上现成的系统会很方便. 本文将教你如何通过阿里云日志服务搭建一套通过Python上传日志.配置日志告警的监控服务. 1.准备 开始之前,你要确保Python和pip已经成功安装在电脑上,如果没有,可以访问这篇文

  • 在python中按照特定顺序访问字典的方法详解

    最近使用python写一些东西,在参考资料的时候发现字典是没有顺序的,那么怎么样按照一定顺序访问字典呐,我找到了一个小方法: 假设一个字典是: D = {'a': '1', 'b': '2', 'c': '3'} 如果我们要按照a, b, c的顺序访问字典,可以借助一个列表,比如说: L = list(D.keys()) L.sort() for key in L: print(key, 'is' D[key]) 输出为: a is 1 b is 2 c is 3 需要倒序的话只需使用倒序函数排

  • 对python tkinter窗口弹出置顶的方法详解

    如果想要python 的tkinter窗口置顶,加上下面两句即可实现root窗口的置顶显示,可以用于某些程序的消息提示,能够弹出到桌面显示 root = Tk() root.wm_attributes('-topmost',1) 以上这篇对python tkinter窗口弹出置顶的方法详解就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们.

  • 基于Python的Post请求数据爬取的方法详解

    为什么做这个 和同学聊天,他想爬取一个网站的post请求 观察 该网站的post请求参数有两种类型:(1)参数体放在了query中,即url拼接参数(2)body中要加入一个空的json对象,关于为什么要加入空的json对象,猜测原因为反爬虫.既有query参数又有空对象体的body参数是一件脑洞很大的事情. 一开始先在apizza网站 上了做了相关实验才发现上面这个规律的,并发现该网站的请求参数要为raw形式,要是直接写代码找规律不是一件容易的事情. 源码 import requests im

  • 对python PLT中的image和skimage处理图片方法详解

    用PLT比较轻量级,用opencv是比较重量级 import numpy as np from PIL import Image if __name__ == '__main__': image_file = '/Users/mac/Documents/学习文档/机器学习/5.Package/son.png' height = 100 #假定写入图片的高度是100 img = Image.open(image_file) img_width, img_height = img.size #获取i

随机推荐