您好,登錄后才能下訂單哦!
這篇文章主要講解了“Django模型層實例分析”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“Django模型層實例分析”吧!
一、F查詢
在上面所有的例子中,我們構造的過濾器都只是將字段值與某個我們自己設定的常量做比較。如果我們要對兩個字段的值做比較,那該怎么做呢?
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
例子:查詢賣出數量大于庫存數的商品名稱
res=models.Goods.objects.filter(sold_out__gt=F('remain')).values_list('name','sold_out','remain')
print(res)
#<QuerySet[('襪子',600,100),('夾克',20,10)]>
F可以幫我們取到表中某個字段對應的值來當作我的篩選條件,而不是我認為自定義常量的條件了,實現了動態比較的效果
Django支持F()對象之間以及F()對象和常數之間的加減乘除和取模的操作。基于此可以對表中的數值類型進行數學運算
例子:將每個商品的價格提高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表示進行字符串的拼接操作,參數位置決定了拼接是在頭部拼接還是尾部拼接,Value里面是要新增的拼接值
二、Q查詢
filter()方法匯總的逗號get的條件是與的關系,如果要執行更復雜的查詢,比如or的語句,就會用到Q對象
例子:
查詢賣出數量大于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即可支持交叉并的比較符
#查詢庫存數是小于等于20,且賣出數不是10的產品
res=models.Goods.objects.filter(Q(remain__lte=20)&~Q(sold_out=12)).values_list('name')
我們可以組合&和|操作符以及使用括號進行分組來編寫任意復雜的Q對象。
同時,Q對象可以使用~操作符取反,這允許組合正常的查詢和取反(NOT)查詢。
#查詢產品名包含新款或者爆款,且庫存大于60的產品
res=models.Goods.objects.filter(Q(name__contains='新款')|Q(name__contains='爆款'),remain__gt=60).values_list('name')
查詢函數可以混合使用Q對象和關鍵字參數。所有提供給查詢函數的參數(關鍵字參數或Q對象)都將"AND”在一起。但是,如果出現Q對象,它必須位于所有關鍵字參數的前面
重點使用方法補充:
實例化Q對象:q=Q()
q.connector='or'#默認q之間的條件都是與關系,這里改成or關系
q.children.append(('name','sgt'))#插入第一個條件,注意這里傳的是一個元祖
q.children.append(('password','123'))#可以繼續插入條件
#q對象支持直接放入filter括號內,它們之間默認是and關系,可以通過上面的q.connect='or'來修改成或關系
models.User.objects.filter(q)#這里面就是查詢的條件們,它們之間默認是與關系,可以修改成or關系
三、事務
定義:將多個sql語句操作變成原子性操作,要么同時成功,有一個失敗在里面就回滾到原來的狀態,保證數據的完整性和一致性(NoSQL數據庫對事務則是部分支持)
#事務
#購買商品
#產品表中修改數據:賣出數+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()的區別
兩者都是對數據的修改保存操作,但是save()函數是將數據列的全部數據項全部重新寫一遍,而update()則是針對修改的項進行針對的更新效率高耗時少
所以以后對數據的修改保存用update()
讓我們通過orm對數據庫操作時候,讓終端顯示內部查詢操作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',
},
}
}
配置好之后,再執行任何對數據庫進行操作的語句時,會自動將Django執行的sql語句打印到pycharm終端上
補充:
除了配置外,還可以通過一點query即可查看查詢語句,具體操作如下:
only與defer
拿到的是一個對象兩者是相反的
(前提設置:設置每次操作數據庫時候都會有sql語句現實在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)構成。顯而易見,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,但不能直接調用get屬性_display方法(模板畢竟是模板語言),要解決這個問題,可以用自定義過濾器來搞定:
來回顧一下如何自定義過濾器:
1,在應用名下新建一個名為templatetags文件夾
2,在該文件夾內新建一個py文件,名字隨意
3,在該py文件內添加固定代碼和自定義過濾器代碼
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批量插入數據
當我們使用orm來一次性新增很多表記錄的時候,等待結果的時間會非常的慢,如果一次性需要批量插入很多數據的時候就需要使用bulk_create來批量插入數據
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連表操作,一次性獲取關聯的數據。
總結:
1.select_related主要針一對一和多對一關系進行優化。
2.select_related使用SQL的JOIN語句進行優化,通過減少SQL查詢的次數來進行優化、提高性能。
defprefetch_related(self,*lookups)
性能相關:多表連表操作時速度會慢,使用其執行多次SQL查詢在Python代碼中實現連表操作。
感謝各位的閱讀,以上就是“Django模型層實例分析”的內容了,經過本文的學習后,相信大家對Django模型層實例分析這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。