Python使用描述器實(shí)現(xiàn)ORM模型的方法詳解
訪問或者修改描述器對(duì)象的屬性時(shí)無法觸發(fā)__setattr__等方法,只會(huì)觸發(fā)描述器類內(nèi)部的__set__,__get__,__delete__方法.
ORM模型:類名對(duì)應(yīng)表名,對(duì)象對(duì)應(yīng)的數(shù)據(jù)行,類屬性對(duì)應(yīng)數(shù)據(jù)行的各字段,有幾個(gè)表字段,就綁定幾個(gè)類屬性;往表中增加數(shù)據(jù)就是創(chuàng)建對(duì)象,每創(chuàng)建一個(gè)對(duì)象,就是增加一行數(shù)據(jù)記錄。
ORM框架的功能:
1.建立模型類和表之間的對(duì)應(yīng)關(guān)系,允許我們通過面向?qū)ο蟮姆绞讲僮鲾?shù)據(jù)庫。
2.根據(jù)設(shè)計(jì)的模型類生成數(shù)據(jù)庫中的表格。
3.通過方便的配置就可以進(jìn)行數(shù)據(jù)庫的切換。
MySql的常用數(shù)據(jù)類型:
1.整數(shù):int,bit
2.小數(shù):decimal(decimal表示浮點(diǎn)數(shù),decimal(5,2)表示共計(jì)5位數(shù),小數(shù)占2位)
3.字符串:varchar(可變長度),char(不可變長度)
4.日期時(shí)間:date,time,datetime
5.枚舉類型:enum
模型類案例:
"""
django的ORM模型字段
BooleanField: 布爾字段,True或False
CharField(max_length=最大長度): 字符串,參數(shù)max_length表示最大字符個(gè)數(shù)
IntegerField: 整數(shù)
"""
class TestReport(BaseTable):
class Meat:
verbose_name = '測(cè)試報(bào)告'
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__方法:設(shè)置屬性
"""
只要一個(gè)類中出現(xiàn)了:
__get__(self,instance,owner)
__set__(self,instance,value)
__delete__(self,instance)
__set_name__(self,owner,name)
中的任意一個(gè)方法,這個(gè)類就不是一個(gè)普通的類了,
應(yīng)被稱為:
描述器類(應(yīng)用在ORM模型中)
"""
class Field(object):
"""
只要一個(gè)類中出現(xiàn)了以下任意一個(gè)方法,這個(gè)類就是一個(gè)描述器類
"""
def __get__(self, instance, owner):
pass
def __set__(self, instance, value):
print('---set---方法被觸發(fā)了')
def __delete__(self, instance):
pass
class Model(object):
attr = Field() # attr是一個(gè)描述器對(duì)象,修改時(shí)無法觸發(fā)__setattr__等方法,
# 只能觸發(fā)描述器類內(nèi)部的__set__方法
if __name__ == '__main__':
m = Model()
m.attr = 666 # 嘗試修改attr屬性
print(m.attr)
# 輸出:
---set - --方法被觸發(fā)了
None
class Field(object):
"""
只要一個(gè)類中出現(xiàn)了以下任意一個(gè)方法,這個(gè)類就是一個(gè)描述器類
"""
def __get__(self, instance, owner):
pass
def __set__(self, instance, value):
"""
:param instance: 修改的對(duì)象
:param value: 修改的值
:return:
"""
print('---set---方法被觸發(fā)了')
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是一個(gè)描述器對(duì)象,修改時(shí)無法觸發(fā)__setattr__等方法,
# 只能觸發(fā)描述器類內(nèi)部的__set__方法
if __name__ == '__main__':
m = Model()
print(m) # <__main__.Model object at 0x7fecc01f8a00>,與instance相同
m.attr = 666 # 嘗試修改attr屬性
2.__get__方法:訪問屬性
"""
只要一個(gè)類中出現(xiàn)了:
__get__(self,instance,owner)
__set__(self,instance,value)
__delete__(self,instance)
__set_name__(self,owner,name)
中的任意一個(gè)方法,這個(gè)類就不是一個(gè)普通的類了,
應(yīng)被稱為:
描述器類(應(yīng)用在ORM模型中)
"""
class Field(object):
"""
只要一個(gè)類中出現(xiàn)了以下任意一個(gè)方法,這個(gè)類就是一個(gè)描述器類
"""
def __get__(self, instance, owner):
print('---get---方法被觸發(fā)了')
def __set__(self, instance, value):
"""
:param instance: 修改的對(duì)象
:param value: 修改的值
:return:
"""
print('---set---方法被觸發(fā)了')
self.value = value
def __delete__(self, instance):
pass
class Model(object):
attr = Field() # attr是一個(gè)描述器對(duì)象,修改時(shí)無法觸發(fā)__setattr__等方法,
# 只能觸發(fā)描述器類內(nèi)部的__set__方法
if __name__ == '__main__':
m = Model()
m.attr = 666 # 嘗試修改attr屬性
print(m.attr)
# 輸出:
---set - --方法被觸發(fā)了
---get - --方法被觸發(fā)了
None
"""
只要一個(gè)類中出現(xiàn)了:
__get__(self,instance,owner)
__set__(self,instance,value)
__delete__(self,instance)
__set_name__(self,owner,name)
中的任意一個(gè)方法,這個(gè)類就不是一個(gè)普通的類了,
應(yīng)被稱為:
描述器類(應(yīng)用在ORM模型中)
"""
class Field(object):
"""
只要一個(gè)類中出現(xiàn)了以下任意一個(gè)方法,這個(gè)類就是一個(gè)描述器類
"""
def __get__(self, instance, owner):
print('---get---方法被觸發(fā)了')
print(instance) # <__main__.Model object at 0x7f80b81a09d0>
print(owner) # <class '__main__.Model'>
return self.value
def __set__(self, instance, value):
"""
:param instance: 修改的對(duì)象
:param value: 修改的值
:return:
"""
print('---set---方法被觸發(fā)了')
self.value = value
def __delete__(self, instance):
pass
class Model(object):
attr = Field() # attr是一個(gè)描述器對(duì)象,修改時(shí)無法觸發(fā)__setattr__等方法,
# 只能觸發(fā)描述器類內(nèi)部的__set__方法
if __name__ == '__main__':
m = Model()
m.attr = 666 # 嘗試修改attr屬性
print(m.attr) # 666
# 輸出:
---set - --方法被觸發(fā)了
---get - --方法被觸發(fā)了
< __main__.Model object at 0x7f80b81a09d0 >
< class '__main__.Model'>
666
3.__delete__方法:刪除屬性
"""
只要一個(gè)類中出現(xiàn)了:
__get__(self,instance,owner)
__set__(self,instance,value)
__delete__(self,instance)
__set_name__(self,owner,name)
中的任意一個(gè)方法,這個(gè)類就不是一個(gè)普通的類了,
應(yīng)被稱為:
描述器類(應(yīng)用在ORM模型中)
"""
class Field(object):
"""
只要一個(gè)類中出現(xiàn)了以下任意一個(gè)方法,這個(gè)類就是一個(gè)描述器類
"""
def __get__(self, instance, owner):
return self.value
def __set__(self, instance, value):
"""
:param instance: 修改的對(duì)象
:param value: 修改的值
:return:
"""
print('---set---方法被觸發(fā)了')
self.value = value
def __delete__(self, instance):
print('---delete---方法被觸發(fā)了')
class Model(object):
attr = Field() # attr是一個(gè)描述器對(duì)象,修改時(shí)無法觸發(fā)__setattr__等方法,
# 只能觸發(fā)描述器類內(nèi)部的__set__方法
if __name__ == '__main__':
m = Model()
m.attr = 666 # 嘗試修改attr屬性
del m.attr # ---delete---方法被觸發(fā)了
print(m.attr) # None
# 輸出:
---set - --方法被觸發(fā)了
---delete - --方法被觸發(fā)了
666
"""
只要一個(gè)類中出現(xiàn)了:
__get__(self,instance,owner)
__set__(self,instance,value)
__delete__(self,instance)
__set_name__(self,owner,name)
中的任意一個(gè)方法,這個(gè)類就不是一個(gè)普通的類了,
應(yīng)被稱為:
描述器類(應(yīng)用在ORM模型中)
"""
class Field(object):
"""
只要一個(gè)類中出現(xiàn)了以下任意一個(gè)方法,這個(gè)類就是一個(gè)描述器類
"""
def __get__(self, instance, owner):
print('---get---方法被觸發(fā)了')
print(instance) # <__main__.Model object at 0x7f80b81a09d0>
print(owner) # <class '__main__.Model'>
return self.value
def __set__(self, instance, value):
"""
:param instance: 修改的對(duì)象
:param value: 修改的值
:return:
"""
print('---set---方法被觸發(fā)了')
self.value = value
def __delete__(self, instance):
print('---delete---方法被觸發(fā)了')
print(instance) # <__main__.Model object at 0x7ff61806a160>
self.value = None
class Model(object):
attr = Field() # attr是一個(gè)描述器對(duì)象,修改時(shí)無法觸發(fā)__setattr__等方法,
# 只能觸發(fā)描述器類內(nèi)部的__set__方法
if __name__ == '__main__':
m = Model()
m.attr = 666 # 嘗試修改attr屬性
del m.attr # ---delete---方法被觸發(fā)了
print(m.attr) # None
# 輸出:
---set - --方法被觸發(fā)了
---delete - --方法被觸發(fā)了
< __main__.Model object at 0x7ff61806a160 >
---get - --方法被觸發(fā)了
< __main__.Model object at 0x7ff61806a160 >
<class '__main__.Model'>
None
4.描述器實(shí)現(xiàn)ORM模型:
"""
通過描述器實(shí)現(xiàn)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:
# 再判斷是否是整數(shù)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只能賦值為整數(shù)
if __name__ == '__main__':
user = UserModel()
user.name = "春田"
print(user.name) # 輸出: 春田
user.age = 130
print(user.age) # 輸出: 130
user.pwd = 'wsdgdgdrgerdsfs方式范德薩發(fā)阿瑟費(fèi)薩法 sfa fda fsdf sdf fg'
print(user.pwd) # 輸出: TypeError: length need less than 40
總結(jié)
本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
Python獲取命令實(shí)時(shí)輸出-原樣彩色輸出并返回輸出結(jié)果的示例
今天小編就為大家分享一篇Python獲取命令實(shí)時(shí)輸出-原樣彩色輸出并返回輸出結(jié)果的示例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2019-07-07
Python爬蟲之Selenium中frame/iframe表單嵌套頁面
這篇文章主要介紹了Python爬蟲之Selenium中frame/iframe表單嵌套頁面,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-12-12
淺談pandas中Dataframe的查詢方法([], loc, iloc, at, iat, ix)
下面小編就為大家分享一篇淺談pandas中Dataframe的查詢方法([], loc, iloc, at, iat, ix),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-04-04
Python數(shù)據(jù)分析numpy的Nan和Inf使用注意點(diǎn)詳解
這篇文章主要為大家介紹了Python數(shù)據(jù)分析numpy的Nan和Inf使用注意點(diǎn),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08
python之從文件讀取數(shù)據(jù)到list的實(shí)例講解
下面小編就為大家分享一篇python之從文件讀取數(shù)據(jù)到list的實(shí)例講解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-04-04
Python統(tǒng)計(jì)節(jié)假日剩余天數(shù)的腳本
過完春節(jié),盼著下一個(gè)節(jié)日,那么如何判斷距離節(jié)假日還有多少天呢?今天小編給大家介紹使用python腳本來解決這個(gè)問題,對(duì)Python統(tǒng)計(jì)節(jié)假日倒計(jì)時(shí)腳本感興趣的朋友一起看看吧2022-02-02
python append、extend與insert的區(qū)別
這篇文章主要介紹了python append、extend與insert的區(qū)別的相關(guān)資料,初學(xué)者對(duì)這幾個(gè)概念經(jīng)常搞混,這里就幫大家理清楚,需要的朋友可以參考下2016-10-10

