溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Django模型層實例分析

發(fā)布時間:2022-03-04 14:00:17 來源:億速云 閱讀:190 作者:iii 欄目:web開發(fā)

這篇文章主要講解了“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字段,比如將上面的表中商品名稱全部尾部加上&lsquo;清倉&rsquo;兩個字,如何操作?

  這里需要使用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模型層實例分析

感謝各位的閱讀,以上就是“Django模型層實例分析”的內(nèi)容了,經(jīng)過本文的學習后,相信大家對Django模型層實例分析這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI