iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > Python >使用Python怎么实现一个ORM模型
  • 928
分享到

使用Python怎么实现一个ORM模型

2023-06-15 01:06:01 928人浏览 独家记忆

Python 官方文档:入门教程 => 点击学习

摘要

本篇文章为大家展示了使用python怎么实现一个ORM模型,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。元类对于元类,我的理解其实也便较浅,大概是这个意思所有的类都是使用元类来进行创建的,而所有的类

本篇文章为大家展示了使用python怎么实现一个ORM模型,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。

元类

对于元类,我的理解其实也便较浅,大概是这个意思

所有的类都是使用元类来进行创建的,而所有的类的父类中必然是object(针对python3),Python中的元类只有一个(type),当然这里不包含自定义元类

下面我们来看下类的创建

class Test:   # 定义一个类    passTest1 = type("Test2",(object,),{"name":"test"})  # 定义一个类print(type(Test))print(type(Test1))-----------------------<class 'type'><class 'type'>

从上面可以看出创建类,其实是有两种方式,一种是通过class关键字来定义,一种是通过type来进行创建,当然常用的是使用class来进行创建了,在看最后的结果,可以看出类的类型为type。说明我们这个类就是由type来创建的

明白了这个之后我们再来梳理下怎么使用自定义元类来创建类,明白一点,自定义元类需要继承type

class MetaClass(type):  # 定义一个元类    passclass Test(metaclass=MetaClass):  # 使用自定义元类来创建类    passprint(type(Test))--------------------------<class '__main__.MetaClass'>

很明显可以看出Test类就是用MetaClass类创建出来的

描述器

从描述器的定义来说,只要一个类中实现了__get__、__set__、__delete__中的一个或几个,这个类的实例就可以叫描述器

下面我们来定义一个简易的描述器

class Describer:    def __set__(self, instance, value):        print("设置属性的时候会被调用")        self.value = value    def __get__(self, instance, owner):        print("获取属性的时候会被调用")        return self.value    def __delete__(self, instance):        print("删除属性的时候会被调用")        self.value = Noneclass Test:    name = Describer()t = Test()t.name = "xxxxx"print(t.name)----------------------设置属性的时候会被调用获取属性的时候会被调用xxxxx

从上面的代码中有没有什么想法?既然__set__方法会在我们设置属性的时候会被调用,那么我们是不是可以在设置属性前对这个属性做一些操作呢?

ORM模型

ORM模型到底是个啥?ORM对于后端研发来说肯定是不陌生的,包括很多后端框架现在都自带这个模型了

ORM(Object Relational Mapping)对象关系映射

既然是对象关系映射,那对象是啥?我的理解为:Python中的类与数据库之间的映射,对数据的操作就不用编写sql语言了,因为都封装好了,比如你想插入一条数据,你就直接创建一个对象即可,

Python ------->>>>      数据库

类名     ------->>>>      数据库中的表名

对象     ------->>>>      数据库中的一行数据

属性     ------->>>>      数据库中的字段

大致就是上面的映射关系

ORM实现步骤

利用描述器实现对数据库字段的类型、长度限制

实现Mode类,也就是Python中的类

利用元类实现映射关系

好,我们先利用描述器来实现对数据字段的类型,长度限制

class BaseFiled:    passclass CharFiled(BaseFiled):    """定义一个字符串的类型限制"""    def __init__(self, length=10):        self.length = length    def __set__(self, instance, value):        if isinstance(value, str):            if len(value) <= self.length:                self.value = value            else:                raise ValueError("length can not exceed {}".format(self.length))        else:            raise TypeError("need a str")    def __get__(self, instance, owner):        return self.value    def __delete__(self, instance):        self.value = Noneclass IntFiled(BaseFiled):    """定义一个数值的类型限制"""    def __set__(self, instance, value):        if isinstance(value, int):            self.value = value        else:            raise TypeError("need a int")    def __get__(self, instance, owner):        return self.value    def __delete__(self, instance):        self.value = Noneclass BoolFiled(BaseFiled):    """定义一个布尔的类型限制"""    def __set__(self, instance, value):        if isinstance(value, bool):            self.value = value        else:            raise TypeError("need a bool")    def __get__(self, instance, owner):        return self.value    def __delete__(self, instance):        self.value = None

上面实现了三种,分别是字符串、数值、布尔值的,下面在来实现元类以及模型类

class MyMateClass(type):    """自定义一个元类"""    def __new__(cls, name: str, bases: tuple, dic: dict, *args, **kwargs):        """        :param name: name为模型类的类名也就是数据库中的表名        :param bases:  bases为一个元祖类型,里面装的是name这个类的父类        :param dic: dic为一个dict类型,装的是name这个类中的属性        :param args:        :param kwargs:        :return:        """        if name == "BaseMode":   # 判断类名是否为BaseMode,如果是则直接使用元类创建类,不做其他任何操作            return super().__new__(cls, name, bases, dic)        else:            table_name = name.lower()  # 将表名变成小写            filed_dic = {}   # 定义一个空的列表,用来装dic中属于BaseFiled类型的属性,因为dic中会有其他创建类时自动生成的属性,这些属性我们没必要去建立映射关系,所以需要将其剔除掉            for k, v in dic.items():                if isinstance(v, BaseFiled):                    filed_dic[k] = v            dic["t_name"] = table_name    # 将表名添加到dic中,实现类名与表名的映射关系            dic["filed_dict"] = filed_dic  # 将属于BaseFiled类型的属性给添加到dic中,实现属性与字段的映射关系            return super().__new__(cls, name, bases, dic)class BaseMode(metaclass=MyMateClass):    def __init__(self, **kwargs):        """        由于每一个模型类(也就是数据库表)的属性个数不一致,所以我们需要定义一个父类来进行定义初始化的属性        :param kwargs:        """        for k, v in kwargs.items():   # 遍历传进来的所有属性            setattr(self, k, v)   # 拿到这些属性后对self(也就是类本身)进行设置属性    def save(self):        """生成SQL语句"""        # 获取表名        table_name = self.t_name        # 获取所有的属性        fileds = self.filed_dict        dic = {}  # 定义一个空字典,用来装属性名和属性值        for k, v in fileds.items():            value = getattr(self, k)            dic[k] = value        sql = "insert into {} values{}".format(table_name, tuple(dic.values()))        return sqlclass User(BaseMode):    name = CharFiled()    age = IntFiled()    love = CharFiled(length=50)    live = BoolFiled()if __name__ == '__main__':    c = User(name="lc", age=12, love="hjh", live=True)    c.save()--------------------------insert into user values('lc', 12, 'hjh', True)

以上就实现了一个简单的ORM模型了,这个虽然在测试开发过程中用的很少(一般都是直接用框架中封装好的),学习这个也是为了更好的理解原理,后面好学习flask以及Django

下面贴一下完整的代码吧

# -*- coding: utf-8 -*-# @Time    : 2021-05-11 10:14# @Author  : cainiao# @File    : Meat.py# @Software: PyCharm# @Content : 实现ORM模型class BaseFiled:    passclass CharFiled(BaseFiled):    """定义一个字符串的类型限制"""    def __init__(self, length=10):        self.length = length    def __set__(self, instance, value):        if isinstance(value, str):            if len(value) <= self.length:                self.value = value            else:                raise ValueError("length can not exceed {}".format(self.length))        else:            raise TypeError("need a str")    def __get__(self, instance, owner):        return self.value    def __delete__(self, instance):        self.value = Noneclass IntFiled(BaseFiled):    """定义一个数值的类型限制"""    def __set__(self, instance, value):        if isinstance(value, int):            self.value = value        else:            raise TypeError("need a int")    def __get__(self, instance, owner):        return self.value    def __delete__(self, instance):        self.value = Noneclass BoolFiled(BaseFiled):    """定义一个数值的类型限制"""    def __set__(self, instance, value):        if isinstance(value, bool):            self.value = value        else:            raise TypeError("need a bool")    def __get__(self, instance, owner):        return self.value    def __delete__(self, instance):        self.value = Noneclass MyMateClass(type):    """自定义一个元类"""    def __new__(cls, name: str, bases: tuple, dic: dict, *args, **kwargs):        """        :param name: name为模型类的类名也就是数据库中的表名        :param bases:  bases为一个元祖类型,里面装的是name这个类的父类        :param dic: dic为一个dict类型,装的是name这个类中的属性        :param args:        :param kwargs:        :return:        """        if name == "BaseMode":   # 判断类名是否为BaseMode,如果是则直接使用元类创建类,不做其他任何操作            return super().__new__(cls, name, bases, dic)        else:            table_name = name.lower()  # 将表名变成小写            filed_dic = {}   # 定义一个空的列表,用来装dic中属于BaseFiled类型的属性,因为dic中会有其他创建类时自动生成的属性,这些属性我们没必要去建立映射关系,所以需要将其剔除掉            for k, v in dic.items():                if isinstance(v, BaseFiled):                    filed_dic[k] = v            dic["t_name"] = table_name    # 将表名添加到dic中,实现类名与表名的映射关系            dic["filed_dict"] = filed_dic  # 将属于BaseFiled类型的属性给添加到dic中,实现属性与字段的映射关系            return super().__new__(cls, name, bases, dic)class BaseMode(metaclass=MyMateClass):    def __init__(self, **kwargs):        """        由于每一个模型类(也就是数据库表)的属性个数不一致,所以我们需要定义一个父类来进行定义初始化的属性        :param kwargs:        """        for k, v in kwargs.items():   # 遍历传进来的所有属性            setattr(self, k, v)   # 拿到这些属性后对self(也就是类本身)进行设置属性    def save(self):        """生成SQL语句"""        # 获取表名        table_name = self.t_name        # 获取所有的属性        fileds = self.filed_dict        dic = {}  # 定义一个空字典,用来装属性名和属性值        for k, v in fileds.items():            value = getattr(self, k)            dic[k] = value        sql = "insert into {} values{}".format(table_name, tuple(dic.values()))        return sqlclass User(BaseMode):    name = CharFiled()    age = IntFiled()    love = CharFiled(length=50)    live = BoolFiled()if __name__ == '__main__':    c = User(name="lc", age=12, love="hjh", live=True)    print(c.save())    # c.name="lc"    # print(c.name)

Python的优点有哪些

1、简单易用,与C/C++、Java、C# 等传统语言相比,Python对代码格式的要求没有那么严格;2、Python属于开源的,所有人都可以看到源代码,并且可以被移植在许多平台上使用;3、Python面向对象,能够支持面向过程编程,也支持面向对象编程;4、Python是一种解释性语言,Python写的程序不需要编译成二进制代码,可以直接从源代码运行程序;5、Python功能强大,拥有的模块众多,基本能够实现所有的常见功能。

上述内容就是使用Python怎么实现一个ORM模型,你们学到知识或技能了吗?如果还想学到更多技能或者丰富自己的知识储备,欢迎关注编程网Python频道。

--结束END--

本文标题: 使用Python怎么实现一个ORM模型

本文链接: https://www.lsjlt.com/news/276518.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作