您好,登錄后才能下訂單哦!
這篇文章主要講解了“Django模型層實例分析”,文中的講解內(nèi)容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“Django模型層實例分析”吧!
一、F查詢
在上面所有的例子中,我們構(gòu)造的過濾器都只是將字段值與某個我們自己設定的常量做比較。如果我們要對兩個字段的值做比較,那該怎么做呢?
Django提供F()來做這樣的比較。F()的實例可以在查詢中引用字段,來比較同一個model實例中兩個不同字段的值。
示例:
建表:
fromdjango.dbimportmodels
classGoods(models.Model):
name=models.CharField(max_length=32)
price=models.DecimalField(max_digits=8,decimal_places=2)
remain=models.BigIntegerField()
sold_out=models.BigIntegerField()
插入模塊
fromdjango.db.modelsimportF,Q
例子:查詢賣出數(shù)量大于庫存數(shù)的商品名稱
res=models.Goods.objects.filter(sold_out__gt=F('remain')).values_list('name','sold_out','remain')
print(res)
#<QuerySet[('襪子',600,100),('夾克',20,10)]>
F可以幫我們?nèi)〉奖碇心硞€字段對應的值來當作我的篩選條件,而不是我認為自定義常量的條件了,實現(xiàn)了動態(tài)比較的效果
Django支持F()對象之間以及F()對象和常數(shù)之間的加減乘除和取模的操作?;诖丝梢詫Ρ碇械臄?shù)值類型進行數(shù)學運算
例子:將每個商品的價格提高50塊
res1=models.Goods.objects.update(price=F('price')+100)
引申:如何修改char字段,比如將上面的表中商品名稱全部尾部加上‘清倉’兩個字,如何操作?
這里需要使用2個模塊:Concat和Value
fromdjango.db.models.functionsimportConcat
fromdjango.db.modelsimportValue
res=models.Goods.objects.update(name=Concat(F('name'),Value('清倉')))
Concat表示進行字符串的拼接操作,參數(shù)位置決定了拼接是在頭部拼接還是尾部拼接,Value里面是要新增的拼接值
二、Q查詢
filter()方法匯總的逗號get的條件是與的關系,如果要執(zhí)行更復雜的查詢,比如or的語句,就會用到Q對象
例子:
查詢賣出數(shù)量大于100或者價格小于300的商品名
fromdjango.db.modelsimportF,Q
res=models.Goods.objects.filter(Q(sold_out__gt=100)|Q(price__lt=300)).values_list('name','sold_out','price')
print(res)
<QuerySet[('襪子清倉',600,Decimal('129.90')),('寸衫清倉',10,Decimal('229.90'))]>
對條件包裹一層Q時候,filter即可支持交叉并的比較符
#查詢庫存數(shù)是小于等于20,且賣出數(shù)不是10的產(chǎn)品
res=models.Goods.objects.filter(Q(remain__lte=20)&~Q(sold_out=12)).values_list('name')
我們可以組合&和|操作符以及使用括號進行分組來編寫任意復雜的Q對象。
同時,Q對象可以使用~操作符取反,這允許組合正常的查詢和取反(NOT)查詢。
#查詢產(chǎn)品名包含新款或者爆款,且?guī)齑娲笥?0的產(chǎn)品
res=models.Goods.objects.filter(Q(name__contains='新款')|Q(name__contains='爆款'),remain__gt=60).values_list('name')
查詢函數(shù)可以混合使用Q對象和關鍵字參數(shù)。所有提供給查詢函數(shù)的參數(shù)(關鍵字參數(shù)或Q對象)都將"AND”在一起。但是,如果出現(xiàn)Q對象,它必須位于所有關鍵字參數(shù)的前面
重點使用方法補充:
實例化Q對象:q=Q()
q.connector='or'#默認q之間的條件都是與關系,這里改成or關系
q.children.append(('name','sgt'))#插入第一個條件,注意這里傳的是一個元祖
q.children.append(('password','123'))#可以繼續(xù)插入條件
#q對象支持直接放入filter括號內(nèi),它們之間默認是and關系,可以通過上面的q.connect='or'來修改成或關系
models.User.objects.filter(q)#這里面就是查詢的條件們,它們之間默認是與關系,可以修改成or關系
三、事務
定義:將多個sql語句操作變成原子性操作,要么同時成功,有一個失敗在里面就回滾到原來的狀態(tài),保證數(shù)據(jù)的完整性和一致性(NoSQL數(shù)據(jù)庫對事務則是部分支持)
#事務
#購買商品
#產(chǎn)品表中修改數(shù)據(jù):賣出數(shù)+1,庫存-1
fromdjango.db.modelsimportF
fromdjango.dbimporttransaction
try:
withtransaction.atomic():
models.Goods.objects.filter(id=1).update(remain=F('remain')-1,sold_out=F('sold_out')+1)
exceptExceptionase:
print(e)
四、補充的一些常用的操作
update()與save()的區(qū)別
兩者都是對數(shù)據(jù)的修改保存操作,但是save()函數(shù)是將數(shù)據(jù)列的全部數(shù)據(jù)項全部重新寫一遍,而update()則是針對修改的項進行針對的更新效率高耗時少
所以以后對數(shù)據(jù)的修改保存用update()
讓我們通過orm對數(shù)據(jù)庫操作時候,讓終端顯示內(nèi)部查詢操作sql語句:
在Django項目的settings.py文件中,在最后復制粘貼如下代碼:
LOGGING={
'version':1,
'disable_existing_loggers':False,
'handlers':{
'console':{
'level':'DEBUG',
'class':'logging.StreamHandler',
},
},
'loggers':{
'django.db.backends':{
'handlers':['console'],
'propagate':True,
'level':'DEBUG',
},
}
}
配置好之后,再執(zhí)行任何對數(shù)據(jù)庫進行操作的語句時,會自動將Django執(zhí)行的sql語句打印到pycharm終端上
補充:
除了配置外,還可以通過一點query即可查看查詢語句,具體操作如下:
only與defer
拿到的是一個對象兩者是相反的
?。ㄇ疤嵩O置:設置每次操作數(shù)據(jù)庫時候都會有sql語句現(xiàn)實在pycharm終端,上面已說明步驟)
先看看only:
看看defer
choice屬性
choice這個屬性,用來限制用戶做出選擇的范圍。比如說性別的選擇(男或女)
classMyUser(models.Model):
name=models.CharField(max_length=32)
password=models.CharField(max_length=32)
choices=((1,'男'),(2,'女'),(3,'其它'))
gender=models.CharField(choices=choices,default=1,max_length=5)
choice接收一個元組(保證值不可變),同理每一個選項也是由一個元組(value,display_name)構(gòu)成。顯而易見,display_name就是要在頁面中展示的。
如何取到value和displayname?
比如說實例一個User對象user_obj,
user_obj.gender=value(通過屬性取value)
user_obj.get_gender_display()=display_name(通過get_屬性_display()方法取display_name)
在模板中可以通過模板語言{{user_obj.gender}}很簡單地顯示value,但不能直接調(diào)用get屬性_display方法(模板畢竟是模板語言),要解決這個問題,可以用自定義過濾器來搞定:
來回顧一下如何自定義過濾器:
1,在應用名下新建一個名為templatetags文件夾
2,在該文件夾內(nèi)新建一個py文件,名字隨意
3,在該py文件內(nèi)添加固定代碼和自定義過濾器代碼
fromdjangoimporttemplate
register=template.Library()
@register.filter(name='displayName')
defdisplayName(obj):
res=obj.get_gender_display
returnres()
#視圖層:
fromdjango.shortcutsimportrender,HttpResponse,reverse
#Createyourviewshere.
fromapp01importmodels
defindex(request):
obj=models.MyUser.objects.filter(pk=1).first()
returnrender(request,'index.html',locals())
#前端(html頁面):
{%loadmy_file%}
{{obj|displayName}}
bulk_create批量插入數(shù)據(jù)
當我們使用orm來一次性新增很多表記錄的時候,等待結(jié)果的時間會非常的慢,如果一次性需要批量插入很多數(shù)據(jù)的時候就需要使用bulk_create來批量插入數(shù)據(jù)
importrandom
user_list=['用戶[{}]'.format(i)foriinrange(100)]
data=[]
forjinuser_list:
data.append(models.MyUser(name=j,password='123',gender=str(random.choice([1,2,3]))))
models.MyUser.objects.bulk_create(data)
select_related和prefetch_related
defselect_related(self,*fields)
性能相關:表之間進行join連表操作,一次性獲取關聯(lián)的數(shù)據(jù)。
總結(jié):
1.select_related主要針一對一和多對一關系進行優(yōu)化。
2.select_related使用SQL的JOIN語句進行優(yōu)化,通過減少SQL查詢的次數(shù)來進行優(yōu)化、提高性能。
defprefetch_related(self,*lookups)
性能相關:多表連表操作時速度會慢,使用其執(zhí)行多次SQL查詢在Python代碼中實現(xiàn)連表操作。
感謝各位的閱讀,以上就是“Django模型層實例分析”的內(nèi)容了,經(jīng)過本文的學習后,相信大家對Django模型層實例分析這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。