日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

django学习之Model(四)MakingQuery

發布時間:2025/3/20 编程问答 16 豆豆
生活随笔 收集整理的這篇文章主要介紹了 django学习之Model(四)MakingQuery 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

上一篇寫到MakingQuey中的filter,本篇接著來。

?10)-擴展多值的關系

如果對一個ManyToManyField或ForeignKey的表進行filter過濾查詢的話,有2中方法可以用。分別是:

#1 Blog.objects.filter(entry__headline__contains='Lennon',entry__pub_date__year=2008)#2 Blog.objects.filter(entry__headline__contains='Lennon').filter(entry__pub_date__year=2008)

假設,現有一個blog表,它對應了很多的entry的表,而且這個blog既有含有“Lennon”的entry,也有含有2008的entry,但是沒有那種2者都有的entry,那么第一個方法過濾的是2者都有的entry,所以沒有符合條件的blog返回。第一種方法可以理解為“并且”的意思。第二種是第一個filter返回含有“Lennon”的blog,然后在這個blog集合中,再選有2008的,所以會有blog返回。開始理解起來很費勁,抓住特點:一個blog對應多個entry。例如,blog1對應了entry1,entry2,entry3,其中entry1只有“Lennon”,沒有2008;entry2只有2008,沒有“Lennon”;entry3則什么都沒有。那么用第一種方法來filter的時候,則沒有滿足既有Lennon又有2008的entry;第二種方法的第一個filter,因為entry1有Lennon,所以blog1為返回值,然后對返回值blog1進行filter,條件為有2008,而blog1中的entry2是有2008的,所以blog1作為返回值。

這個也適用于exlude().

11)-filters可以引用model中的fields

class F

目前為止的例子中,都是用field中的值來作為filter的條件來進行數據查詢。但是如果需要把一個field的值與他所在的model的其他field的值呢?

django提供F()表達式來實現這種比較。F()的實例是在一個query中來對model中的field進行引用。這些引用可以作為filter的條件來進行過濾。

例如,要查詢blog的entry,comments滿足的數量比pingbacks的多,可以用F()來作用在pingbacks上,然后把結果作為filter的條件:

>>> from django.db.models import F >>> Entry.objects.filter(n_comments__gt=F('n_pingbacks'))

注意:F()表達式中是n_comments比大n_pingbacks。所以,也有倍數、加、減這樣的操作可以來比較:

>>> Entry.objects.filter(n_comments__gt=F('n_pingbacks') * 2)# n_comments比n_pingbacks的2倍多

>>> Entry.objects.filter(rating__lt=F('n_comments') + F('n_pingbacks'))#n_comments與n_pingbacks的和比rating多

gt是多理解為>,lt理解為<.?

而下面的例子則是兩個字符串一樣:

>>> Entry.objects.filter(authors__name=F('blog__name'))

12)-pk

是primary key的意思:

>>> Blog.objects.get(id__exact=14) # Explicit form >>> Blog.objects.get(id=14) # __exact is implied >>> Blog.objects.get(pk=14) # pk implies id__exact # Get blogs entries with id 1, 4 and 7 >>> Blog.objects.filter(pk__in=[1,4,7])# Get all blog entries with id > 14 >>> Blog.objects.filter(pk__gt=14)

同樣應該有這些符號的組合,分別是__雙下劃線,lt,gt,exact等等。

如果查詢含有%符號的,下例給出:

>>> Entry.objects.filter(headline__contains='%')

同樣的_下劃線符號也是,django會自動來處理的,就像上邊這行程序這樣寫就行了。

5-QuerySet的緩存

每個QuerySet都有緩存來降低對數據庫database的訪問。弄明白了之后,可以寫出高效率的代碼。

在新創建的QuerySet中,緩存是空的。當QuerySet第一次 被計算的時候,django把QuerySet放在其緩存中,然后把具體要查詢的數據項作為結果返回。把QuerySet這種緩存的行為時刻記住,有的時候很容易使用不當的。例如下面,建立了2個QuerySet,分別使用后,就丟掉了,這樣造成了2次訪問database,而且第二個e很可能不是第一個e,因為在第二個發生之前,database很可能已經被寫入新數據或刪除什么東西了:

>>> print([e.headline for e in Entry.objects.all()]) >>> print([e.pub_date for e in Entry.objects.all()])

正確的做法如下,建立個變量來存放QuerySet,讓它一直放在內存中,然后每次用的時候從內存中去讀取:

>>> queryset = Entry.objects.all() >>> print([p.headline for p in queryset]) # Evaluate the query set. >>> print([p.pub_date for p in queryset]) # Re-use the cache from the evaluation.

注意,第一行并沒有touch the database,訪問數據庫發生在第二行代碼。

QuerySet也并不是總緩存結果的,當計算queryset的一部分的時候,要緩存,但是如果只是用一個下一層的queryset來訪問結果的時候,并沒有緩存。這也意味著,可以用數組分片或者一個索引來限制queryset而不產生緩存,例如下面的例子,顯示只定義了一個queryset來存放objects,然后用數組來訪問其中的某一個,這樣就沒有緩存,每次都要重新訪問數據庫:

>>> queryset = Entry.objects.all() >>> print queryset[5] # Queries the database >>> print queryset[5] # Queries the database again

然而,如果整個queryset都被計算了,那么就會產生緩存:

>>> queryset = Entry.objects.all() >>> [entry for entry in queryset] # Queries the database >>> print queryset[5] # Uses cache >>> print queryset[5] # Uses cache

還有一些例子也是整個querset都被計算了,當然產生了緩存:

>>> [entry for entry in queryset] >>> bool(queryset) >>> entry in queryset >>> list(queryset)

6-用Q對象來進行復雜的查詢

在filter()方法中,用關鍵字來查詢,這些關鍵字是AND的關系,即”并且“,如果需要進行更復雜的查詢,例如OR關系,可以用Q對象這種方法。

Q對象(django.db.models.Q)是用來封裝關鍵字的集合的。這些關鍵字包括上文的lookup查詢中所提到的關鍵字。例如,下面這個Q對象封裝了LIKE查詢:

from django.db.models import Q Q(question__startswith='What')

Q對象可以用邏輯符號&或者|來連接,結果返回一個Q對象:

Q(question__startswith='Who') | Q(question__startswith='What')

同等于SQL語句:

WHERE question LIKE 'Who%' OR question LIKE 'What%'

可以把Q對象組合成復雜的表達,也可以用~符號,代表”NOT,非“的意思:

Q(question__startswith='Who') | ~Q(pub_date__year=2005)

每個查詢函數(filter(), get(), exclude())都需要有關鍵字,Q對象就可以作為這些查詢函數的關鍵字:

Poll.objects.get(Q(question__startswith='Who'),Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)) )

翻譯成SQL語句就相當痛苦了:

SELECT * from polls WHERE question LIKE 'Who%'AND (pub_date = '2005-05-02' OR pub_date = '2005-05-06')

查詢函數也可以混合使用keywords和Q object,但是要注意,Q object必須在keyword之前定義:

#正確的 Poll.objects.get(Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)),question__startswith='Who') #錯誤的 Poll.objects.get(question__startswith='Who',Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)))

?7-比較對象

用python標準的比較操作符==就可以進行model實例的比較。而這實際上實在比較primarykey的值:

>>> some_entry == other_entry >>> some_entry.id == other_entry.id#實際上

如果model的primarykey不叫id,沒關系,照樣還是在比較primarykey,例如一個model的primarykey是name,則下面2行代碼是同樣意思的:

>>> some_obj == other_obj >>> some_obj.name == other_obj.name

8-刪除對象

delete()用來進行對象的刪除,而且是立即生效,并且沒有返回值:

e.delete()

也可以批量來進行刪除操作,每個QuerySet都有delete()操作,可以把QuerySet中的所有對象都刪掉:

Entry.objects.filter(pub_date__year=2005).delete()

delete是Manager的一個方法,但是由于怕用戶誤操作而沒有顯式的顯現出來。因為delete是純粹的在SQL中執行的方法,所以不需要用戶在過程中去認為的調用。如果你在一個model的class定義中自己定義了一個delete()的話,那么就相當于覆蓋掉了Manager提供的delete,這樣就需要用戶自己去調用了,而且這種自己定義的delete()還不能批量的來操作,也就是不能作為QuerySet中的參數來調用,而是需要自己對每個object單獨進行delete一次。

django提供的delete()方法,會刪除由foreignkey來關聯到一起的object:

b = Blog.objects.get(pk=1) # This will delete the Blog and all of its Entry objects. b.delete()

這種串聯的用法是通過?on_delete?參數傳遞給Foreignkey的。

delete是Manager的一個方法,為了防止用戶誤操作,所以不用顯式調用,但是如果確實需要調用delete()來刪除所有的objects的話,應該明確的指出來這個QuerySet:

Entry.objects.all().delete()

9-復制model實例

盡管沒有built-in的方法來實現model 實例的復制,但是可以用model的所有的fields的值來創建一個新的實例,最簡單的情況就是,先把pk設置成None,然后再save:

1 blog = Blog(name='My blog', tagline='Blogging is easy') 2 blog.save() # blog.pk == 1 3 4 blog.pk = None 5 blog.save() # blog.pk == 2

思考:也就是,第1行代碼只是把Blog內容放在了blog這個變量中,并沒寫進去數據庫,只有調用save()方法時,才發生寫的操作。而且每當調用save(),都相當于要把這個數據(blog)寫進數據庫。而數據庫的pk是唯一而不能重復的,所有先要把blog.pk設成None,然后再操作,由SQL語句把pk由依次遞增為2了。

如果有model的繼承時,會略復雜一些:

class ThemeBlog(Blog):theme = models.CharField(max_length=200)django_blog = ThemeBlog(name='Django', tagline='Django is easy', theme='python') django_blog.save() # django_blog.pk == 3

因為繼承的工作原理,這次需要把pk和id都設成None了:

django_blog.pk = None django_blog.id = None django_blog.save() # django_blog.pk == 4

這個過程并沒有復制相關聯的objects,如果想要復制這種關系,需要多寫一些代碼了。在本文的例子中,Entry和Author是多對多的關系(ManyToManyField):

1 entry = Entry.objects.all()[0] # some previous entry 2 old_authors = entry.authors.all() 3 entry.pk = None 4 entry.save() 5 entry.authors = old_authors # saves new many2many relations

今天到這,明天繼續!

轉載于:https://www.cnblogs.com/ee2213/p/3919669.html

總結

以上是生活随笔為你收集整理的django学习之Model(四)MakingQuery的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 日本少妇吞精囗交 | 熟女俱乐部一区二区视频在线 | 日本一区二区三区在线观看 | 大色综合 | 韩国伦理电影免费在线 | 色香视频首页 | 狠久久| 日韩国产小视频 | 91精品国产91久久久久久久久久久久 | 偷自在线 | 好吊在线视频 | 精品国产一二三四区 | 亚洲人体一区 | 影音先锋亚洲一区 | 欧美中文字幕一区二区 | 毛片日韩 | 中文字幕精品三级久久久 | 日本黄色大片视频 | 韩国美女视频在线观看18 | 美女黄污网站 | 国产欧美日韩在线 | 日本乱淫视频 | 91精品国产乱码久久久久久久久 | 日韩一区二区三区精 | 精品一区二区三区免费看 | 君岛美绪在线 | 欧美大片免费 | av不卡免费在线观看 | 日韩欧美中文字幕在线观看 | 国产一级片播放 | 污漫在线观看 | 四虎国产精品成人免费入口 | 亚洲精品伊人 | 免费网站成人 | 亚洲av无码一区二区乱子伦as | 欧美a v在线播放 | 少妇粉嫩小泬喷水视频www | 黄色亚洲精品 | 精品国产乱码 | 最新黄色av网站 | 丰满熟妇人妻中文字幕 | 日本视频免费看 | 一级特级毛片 | 三叶草欧洲码在线 | 亚州黄色 | 91福利在线导航 | 91n视频 | 蜜桃av在线播放 | 超碰人体| 伊人免费视频 | 欧美在线二区 | 超薄肉色丝袜一二三 | 国产你懂的 | 人妻丝袜一区二区三区 | 欧美一区永久视频免费观看 | 成人免费黄色大片v266 | 91精品国产综合久久久密臀九色 | 国产精品影音先锋 | 就爱啪啪网站 | 成人刺激视频 | 欧美亚洲精品天堂 | 森林影视官网在线观看 | 日本一区二区三区中文字幕 | 日韩午夜激情视频 | 精品亚洲一区二区三区四区五区 | 羞羞动漫免费观看 | 亚洲熟妇中文字幕五十中出 | 亚洲色图激情 | 国产欧美久久久久久 | www视频免费观看 | 亚洲成人手机在线 | 日韩国产精品视频 | 性a视频| 亚洲人性生活视频 | 亚洲一二三区在线观看 | heyzo朝桐光一区二区 | 欧美一级片网站 | 午夜精品久久久久久久第一页按摩 | 黄色片在哪看 | 日韩影视在线 | wwwxxx在线观看| 麻豆久久久久久久 | av亚洲在线观看 | 欧美另类天堂 | 欧美熟妇精品一区二区 | 国产区欧美区日韩区 | 欧美精品一区二区在线播放 | 久久1234 | 亚洲精品男人的天堂 | 日本毛片视频 | bl动漫在线观看 | 日本一区二区免费电影 | 67194午夜| 90岁老太婆乱淫 | aa免费视频 | 中文字幕欧美在线 | 成人毛片视频网站 | 亚洲精品另类 | 中文字幕人乱码中文字 |