av一区二区在线观看_亚洲男人的天堂网站_日韩亚洲视频_在线成人免费_欧美日韩精品免费观看视频_久草视

您的位置:首頁技術(shù)文章
文章詳情頁

如何使用Python實(shí)現(xiàn)一個(gè)簡易的ORM模型

瀏覽:5日期:2022-06-19 18:44:35
目錄元類描述器

本文記錄下自己使用Python實(shí)現(xiàn)一個(gè)簡易的ORM模型

使用到的知識(shí)

1、元類

2、描述器

元類

對(duì)于元類,我的理解其實(shí)也便較淺,大概是這個(gè)意思

所有的類都是使用元類來進(jìn)行創(chuàng)建的,而所有的類的父類中必然是object(針對(duì)Python3),Python中的元類只有一個(gè)(type),當(dāng)然這里不包含自定義元類

下面我們來看下類的創(chuàng)建

class Test: # 定義一個(gè)類 passTest1 = type('Test2',(object,),{'name':'test'}) # 定義一個(gè)類print(type(Test))print(type(Test1))-----------------------<class ’type’><class ’type’>

從上面可以看出創(chuàng)建類,其實(shí)是有兩種方式,一種是通過class關(guān)鍵字來定義,一種是通過type來進(jìn)行創(chuàng)建,當(dāng)然常用的是使用class來進(jìn)行創(chuàng)建了,在看最后的結(jié)果,可以看出類的類型為type。說明我們這個(gè)類就是由type來創(chuàng)建的

明白了這個(gè)之后我們?cè)賮硎崂硐略趺词褂米远x元類來創(chuàng)建類,明白一點(diǎn),自定義元類需要繼承type

class MetaClass(type): # 定義一個(gè)元類 passclass Test(metaclass=MetaClass): # 使用自定義元類來創(chuàng)建類 passprint(type(Test))--------------------------<class ’__main__.MetaClass’>

很明顯可以看出Test類就是用MetaClass類創(chuàng)建出來的

描述器

從描述器的定義來說,只要一個(gè)類中實(shí)現(xiàn)了__get__、__set__、__delete__中的一個(gè)或幾個(gè),這個(gè)類的實(shí)例就可以叫描述器

下面我們來定義一個(gè)簡易的描述器

class Describer: def __set__(self, instance, value):print('設(shè)置屬性的時(shí)候會(huì)被調(diào)用')self.value = value def __get__(self, instance, owner):print('獲取屬性的時(shí)候會(huì)被調(diào)用')return self.value def __delete__(self, instance):print('刪除屬性的時(shí)候會(huì)被調(diào)用')self.value = Noneclass Test: name = Describer()t = Test()t.name = 'xxxxx'print(t.name)----------------------設(shè)置屬性的時(shí)候會(huì)被調(diào)用獲取屬性的時(shí)候會(huì)被調(diào)用xxxxx

從上面的代碼中有沒有什么想法?既然__set__方法會(huì)在我們?cè)O(shè)置屬性的時(shí)候會(huì)被調(diào)用,那么我們是不是可以在設(shè)置屬性前對(duì)這個(gè)屬性做一些操作呢?

ORM模型

ORM模型到底是個(gè)啥?ORM對(duì)于后端研發(fā)來說肯定是不陌生的,包括很多后端框架現(xiàn)在都自帶這個(gè)模型了

ORM(Object Relational Mapping)對(duì)象關(guān)系映射

既然是對(duì)象關(guān)系映射,那對(duì)象是啥?我的理解為:Python中的類與數(shù)據(jù)庫之間的映射,對(duì)數(shù)據(jù)的操作就不用編寫SQL語言了,因?yàn)槎挤庋b好了,比如你想插入一條數(shù)據(jù),你就直接創(chuàng)建一個(gè)對(duì)象即可,

Python ------->>>> 數(shù)據(jù)庫

類名 ------->>>> 數(shù)據(jù)庫中的表名

對(duì)象 ------->>>> 數(shù)據(jù)庫中的一行數(shù)據(jù)

屬性 ------->>>> 數(shù)據(jù)庫中的字段

大致就是上面的映射關(guān)系

ORM實(shí)現(xiàn)步驟

1、利用描述器實(shí)現(xiàn)對(duì)數(shù)據(jù)庫字段的類型、長度限制

2、實(shí)現(xiàn)Mode類,也就是Python中的類

3、利用元類實(shí)現(xiàn)映射關(guān)系

好,我們先利用描述器來實(shí)現(xiàn)對(duì)數(shù)據(jù)字段的類型,長度限制

class BaseFiled: passclass CharFiled(BaseFiled): '''定義一個(gè)字符串的類型限制''' 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): '''定義一個(gè)數(shù)值的類型限制''' def __set__(self, instance, value):if isinstance(value, int): self.value = valueelse: raise TypeError('need a int') def __get__(self, instance, owner):return self.value def __delete__(self, instance):self.value = Noneclass BoolFiled(BaseFiled): '''定義一個(gè)布爾的類型限制''' def __set__(self, instance, value):if isinstance(value, bool): self.value = valueelse: raise TypeError('need a bool') def __get__(self, instance, owner):return self.value def __delete__(self, instance):self.value = None

上面實(shí)現(xiàn)了三種,分別是字符串、數(shù)值、布爾值的,下面在來實(shí)現(xiàn)元類以及模型類

class MyMateClass(type): '''自定義一個(gè)元類''' def __new__(cls, name: str, bases: tuple, dic: dict, *args, **kwargs):''':param name: name為模型類的類名也就是數(shù)據(jù)庫中的表名:param bases: bases為一個(gè)元祖類型,里面裝的是name這個(gè)類的父類:param dic: dic為一個(gè)dict類型,裝的是name這個(gè)類中的屬性:param args::param kwargs::return:'''if name == 'BaseMode': # 判斷類名是否為BaseMode,如果是則直接使用元類創(chuàng)建類,不做其他任何操作 return super().__new__(cls, name, bases, dic)else: table_name = name.lower() # 將表名變成小寫 filed_dic = {} # 定義一個(gè)空的列表,用來裝dic中屬于BaseFiled類型的屬性,因?yàn)閐ic中會(huì)有其他創(chuàng)建類時(shí)自動(dòng)生成的屬性,這些屬性我們沒必要去建立映射關(guān)系,所以需要將其剔除掉 for k, v in dic.items():if isinstance(v, BaseFiled): filed_dic[k] = v dic['t_name'] = table_name # 將表名添加到dic中,實(shí)現(xiàn)類名與表名的映射關(guān)系 dic['filed_dict'] = filed_dic # 將屬于BaseFiled類型的屬性給添加到dic中,實(shí)現(xiàn)屬性與字段的映射關(guān)系 return super().__new__(cls, name, bases, dic)class BaseMode(metaclass=MyMateClass): def __init__(self, **kwargs):'''由于每一個(gè)模型類(也就是數(shù)據(jù)庫表)的屬性個(gè)數(shù)不一致,所以我們需要定義一個(gè)父類來進(jìn)行定義初始化的屬性:param kwargs:'''for k, v in kwargs.items(): # 遍歷傳進(jìn)來的所有屬性 setattr(self, k, v) # 拿到這些屬性后對(duì)self(也就是類本身)進(jìn)行設(shè)置屬性 def save(self):'''生成SQL語句'''# 獲取表名table_name = self.t_name# 獲取所有的屬性fileds = self.filed_dictdic = {} # 定義一個(gè)空字典,用來裝屬性名和屬性值for k, v in fileds.items(): value = getattr(self, k) dic[k] = valuesql = '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)

以上就實(shí)現(xiàn)了一個(gè)簡單的ORM模型了,這個(gè)雖然在測試開發(fā)過程中用的很少(一般都是直接用框架中封裝好的),學(xué)習(xí)這個(gè)也是為了更好的理解原理,后面好學(xué)習(xí)flask以及Django。

下面貼一下完整的代碼吧

# -*- coding: utf-8 -*-# @Time : 2021-05-11 10:14# @Author : cainiao# @File : Meat.py# @Software: PyCharm# @Content : 實(shí)現(xiàn)ORM模型class BaseFiled: passclass CharFiled(BaseFiled): '''定義一個(gè)字符串的類型限制''' 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): '''定義一個(gè)數(shù)值的類型限制''' def __set__(self, instance, value):if isinstance(value, int): self.value = valueelse: raise TypeError('need a int') def __get__(self, instance, owner):return self.value def __delete__(self, instance):self.value = Noneclass BoolFiled(BaseFiled): '''定義一個(gè)數(shù)值的類型限制''' def __set__(self, instance, value):if isinstance(value, bool): self.value = valueelse: raise TypeError('need a bool') def __get__(self, instance, owner):return self.value def __delete__(self, instance):self.value = Noneclass MyMateClass(type): '''自定義一個(gè)元類''' def __new__(cls, name: str, bases: tuple, dic: dict, *args, **kwargs):''':param name: name為模型類的類名也就是數(shù)據(jù)庫中的表名:param bases: bases為一個(gè)元祖類型,里面裝的是name這個(gè)類的父類:param dic: dic為一個(gè)dict類型,裝的是name這個(gè)類中的屬性:param args::param kwargs::return:'''if name == 'BaseMode': # 判斷類名是否為BaseMode,如果是則直接使用元類創(chuàng)建類,不做其他任何操作 return super().__new__(cls, name, bases, dic)else: table_name = name.lower() # 將表名變成小寫 filed_dic = {} # 定義一個(gè)空的列表,用來裝dic中屬于BaseFiled類型的屬性,因?yàn)閐ic中會(huì)有其他創(chuàng)建類時(shí)自動(dòng)生成的屬性,這些屬性我們沒必要去建立映射關(guān)系,所以需要將其剔除掉 for k, v in dic.items():if isinstance(v, BaseFiled): filed_dic[k] = v dic['t_name'] = table_name # 將表名添加到dic中,實(shí)現(xiàn)類名與表名的映射關(guān)系 dic['filed_dict'] = filed_dic # 將屬于BaseFiled類型的屬性給添加到dic中,實(shí)現(xiàn)屬性與字段的映射關(guān)系 return super().__new__(cls, name, bases, dic)class BaseMode(metaclass=MyMateClass): def __init__(self, **kwargs):'''由于每一個(gè)模型類(也就是數(shù)據(jù)庫表)的屬性個(gè)數(shù)不一致,所以我們需要定義一個(gè)父類來進(jìn)行定義初始化的屬性:param kwargs:'''for k, v in kwargs.items(): # 遍歷傳進(jìn)來的所有屬性 setattr(self, k, v) # 拿到這些屬性后對(duì)self(也就是類本身)進(jìn)行設(shè)置屬性 def save(self):'''生成SQL語句'''# 獲取表名table_name = self.t_name# 獲取所有的屬性fileds = self.filed_dictdic = {} # 定義一個(gè)空字典,用來裝屬性名和屬性值for k, v in fileds.items(): value = getattr(self, k) dic[k] = valuesql = '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實(shí)現(xiàn)一個(gè)簡易的ORM模型的詳細(xì)內(nèi)容,更多關(guān)于python 實(shí)現(xiàn)ORM模型的資料請(qǐng)關(guān)注好吧啦網(wǎng)其它相關(guān)文章!

標(biāo)簽: Python 編程
相關(guān)文章:
主站蜘蛛池模板: 黄视频欧美 | 在线看免费 | 亚洲成人一区二区三区 | 伊人免费观看视频 | 色偷偷人人澡人人爽人人模 | 在线四虎| 毛片一级片 | 日韩精品一区二区三区中文在线 | 伊人99| 国产日韩欧美在线播放 | 久久丁香 | 亚洲一区二区三区四区五区中文 | 国产精品久久二区 | 欧美一区免费 | 精品亚洲国产成av人片传媒 | 精品国产区 | 免费视频一区二区 | 日韩三片 | 日本中文字幕在线视频 | 亚洲日日操 | 国产一区二区精 | 99久久精品免费看国产四区 | 99这里只有精品视频 | 亚洲精品久久久久久久久久久 | 99热精品6 | 国产精品久久久久久久久免费丝袜 | 欧美国产亚洲一区二区 | 最近免费日本视频在线 | 日本超碰| 美国一级毛片a | 在线播放国产一区二区三区 | 亚洲欧美一区二区三区视频 | 欧美99| 天堂一区二区三区 | 久久久www成人免费无遮挡大片 | 国产高清av免费观看 | 欧美久久久久久久 | cao在线| 日本理论片好看理论片 | 国产一区亚洲二区三区 | 午夜免费网站 |