python3:通过实例讲解元类实现_ORM01

本文深入探讨了ORM(Object-Relational Mapping)的概念及其在Python中的应用,通过具体示例展示了如何使用属性描述符对数据库字段进行有效校验,确保数据的完整性和一致性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

ORM全称“Object Relational Mapping”,即对象-关系映射,就是把关系数据库的一行映射为一个对象,也就是一个类对应一个表,这样,写代码更简单,不用直接操作SQL语句。

明确下我们的需求:
我们要创建一个类,并把类映射到数据库的一张表,并校验数据库每个字段的取值.
目的:脱离SQL 语句.

class  User:
    name=CharField(db_column="",max_length=10)
    #定义表的列 name 字段,db_columns是表列名称,并用max_length 校验字段的长度
    age=IntField(db_column="",min_length=0,max_length=100)
    # 定义表的列 name 字段,db_columns是表列名称,并用max_length and min_length 校验字段的长度

    class Meta:
        db_table=""
    #添加Meta class 有两个目的 ,1.添加表名称 2.和表的列分开,这样思路比较清晰

user=User()
#实例化User
user.name="Andy"   
#定义name
user.age=120
#定义age  

我们的需求是对表的列进行校验,当年龄是str和name是int 类型都需要报错的,
显然直接赋值的路是行不通的.
怎么才能达到对属性的值进行校验呢,这就要用到前面章节讲到的属性描述符
不懂得可以翻翻看看我的这个章节讲的很细.

开始补充我们的用例,( name=CharField(db_column="",max_length=10))
编写CharField 类

class CharField:
    def __get__(self, instance, owner):
        pass
    def __set__(self, instance, value):
        pass

对set和 get 方法进行重写

完成的属性描述符代码请看下边:

class CharField:
    def __init__(self,db_column,max_length=None):
        self.db_column=db_column
        self.max_length=max_length
        if max_length is not None:
            if not isinstance(max_length,int):
                print("最大值要是int类型")
            elif max_length<0:
                print("不能小于0")
    def __get__(self, instance, owner):
        return self.value
    def __set__(self, instance, value):
        if isinstance(value,str) and len(value)<self.max_length:
            self.value=value
        else:
            print("字符串的长度不能大于最大值  和必须是string 类型")
class IntField:
    def __init__(self,db_column,max=None,min=None):
        self.min_length=min
        self.db_column=db_column
        self.max_length=max
        if max is not None:
            if not isinstance(max,int):
                print("最大值要是int类型")
            elif max<0:
                print("不能小于0")
        if min is not None:
            if not isinstance(max,int):
                print("最大值要是int类型")
            elif max<0:
                print("不能小于0")
        if max is not None and min is not None:
            if min>max:
                print("最大值怎么可能大于最小值呢")

    def __get__(self, instance, owner):
        return self.value
    def __set__(self, instance, value):
        if isinstance(value,int) and self.min_length<value<self.max_length:
            self.value=value
        else:
            print("请检查年龄是否合法")
class  User:
    name=CharField(db_column="",max_length=10)
    #定义表的列 name 字段,db_columns是表列名称,并用max_length 校验字段的长度
    age=IntField(db_column="",min=0,max=100)
    # 定义表的列 name 字段,db_columns是表列名称,并用max_length and min_length 校验字段的长度

    class Meta:
        db_table=""
    #添加Meta class 有两个目的 ,1.添加表名称 2.和表的列分开,这样思路比较清晰

user=User()
user.name=0   #字符串的长度不能大于最大值  和必须是string 类型
user.age=1000  #请检查年龄是否合法   
user.name="Andy"
user.age=10
print(user.name,user.age) # Andy 10

代码逻辑没有问题,校验是好的,保存值也没有问题.
上边的重写要注意:
1.set 校验是针对设置的值
2.init 里面的校验是针对我们实例化的时候.这个要搞清楚,不然理解起来很费劲.

有了属性描述符以后,下边就是我们的重点 要写metaclass 类

请关注下一章节的更新. 谢谢

第一时间知道更新,请关注我

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值