您好,登錄后才能下訂單哦!
本篇文章為大家展示了使用Python怎么實現一個ORM模型,內容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。
對于元類,我的理解其實也便較淺,大概是這個意思
所有的類都是使用元類來進行創建的,而所有的類的父類中必然是object(針對Python3),Python中的元類只有一個(type),當然這里不包含自定義元類
下面我們來看下類的創建
class Test: # 定義一個類 pass Test1 = type("Test2",(object,),{"name":"test"}) # 定義一個類 print(type(Test)) print(type(Test1))----------------------- <class 'type'><class 'type'>
從上面可以看出創建類,其實是有兩種方式,一種是通過class關鍵字來定義,一種是通過type來進行創建,當然常用的是使用class來進行創建了,在看最后的結果,可以看出類的類型為type。說明我們這個類就是由type來創建的
明白了這個之后我們再來梳理下怎么使用自定義元類來創建類,明白一點,自定義元類需要繼承type
class MetaClass(type): # 定義一個元類 pass class Test(metaclass=MetaClass): # 使用自定義元類來創建類 pass print(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 = None class Test: name = Describer() t = Test() t.name = "xxxxx" print(t.name) ---------------------- 設置屬性的時候會被調用 獲取屬性的時候會被調用 xxxxx
從上面的代碼中有沒有什么想法?既然__set__方法會在我們設置屬性的時候會被調用,那么我們是不是可以在設置屬性前對這個屬性做一些操作呢?
ORM模型
ORM模型到底是個啥?ORM對于后端研發來說肯定是不陌生的,包括很多后端框架現在都自帶這個模型了
ORM(Object Relational Mapping)對象關系映射
既然是對象關系映射,那對象是啥?我的理解為:Python中的類與數據庫之間的映射,對數據的操作就不用編寫SQL語言了,因為都封裝好了,比如你想插入一條數據,你就直接創建一個對象即可,
Python ------->>>> 數據庫
類名 ------->>>> 數據庫中的表名
對象 ------->>>> 數據庫中的一行數據
屬性 ------->>>> 數據庫中的字段
大致就是上面的映射關系
ORM實現步驟
1、利用描述器實現對數據庫字段的類型、長度限制
2、實現Mode類,也就是Python中的類
3、利用元類實現映射關系
好,我們先利用描述器來實現對數據字段的類型,長度限制
class BaseFiled: pass class 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 = None class 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 = None class 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 sql class 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: pass class 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 = None class 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 = None class 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 sql class 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)
1、簡單易用,與C/C++、Java、C# 等傳統語言相比,Python對代碼格式的要求沒有那么嚴格;2、Python屬于開源的,所有人都可以看到源代碼,并且可以被移植在許多平臺上使用;3、Python面向對象,能夠支持面向過程編程,也支持面向對象編程;4、Python是一種解釋性語言,Python寫的程序不需要編譯成二進制代碼,可以直接從源代碼運行程序;5、Python功能強大,擁有的模塊眾多,基本能夠實現所有的常見功能。
上述內容就是使用Python怎么實現一個ORM模型,你們學到知識或技能了嗎?如果還想學到更多技能或者豐富自己的知識儲備,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。