Django QuestSet API (官方文檔)
1、返回新查詢集的方法
(1)filter():濾指定條件的結果
Entry.objects.filter(pub_date__gt=datetime.date(2005, 1, 3), headline=‘Hello‘)
SQL語句:
SELECT ...
WHERE (pub_date > ‘2005-1-3‘ AND headline = ‘Hello‘)
(2)exclude():排除指定條件的結果
Entry.objects.exclude(pub_date__gt=datetime.date(2005, 1, 3), headline=‘Hello‘)
SQL語句:
SELECT ...
WHERE NOT (pub_date > ‘2005-1-3‘ AND headline = ‘Hello‘)
(3)annotate():用提供的查詢表達式列表註釋QuerySet中的每個對象。表達式可以是一個簡單的值,對模型(或任何相關模型)上的字段的引用,
或者是對與QuerySet中的對象相關的對象進行計算的聚合表達式(平均值、和等)。annotate()的每個參數都是一個註釋,它將被
添加到返回的QuerySet中的每個對象中。
>>> from django.db.models import Count >>> q = Blog.objects.annotate(Count(‘entry‘)) # The name of the first blog>>> q[0].name ‘Blogasaurus‘ # The number of entries on the first blog >>> q[0].entry__count 42 # 沒有指定關鍵字參數,列和聚合函數的名字決定別名 >>> q = Blog.objects.annotate(number_of_entries=Count(‘entry‘)) # The number of entries on the first blog, using the name provided >>> q[0].number_of_entries42 # 指定關鍵字參數,聚合別名為關鍵字參數
(4)order_by():指定字段排序
默認升序,字段名前加負號降序,?代表隨機排序(浪費時間與性能,主要看你用的後端)
Entry.objects.filter(pub_date__year=2005).order_by(‘-pub_date‘, ‘headline‘) # 先按照pub_date 降序排列,然後headline升序排列
要按不同模型中的字段排序,使用與查詢模型關系相同的語法。也就是說,字段名後面跟著雙下劃線(__),後面跟著新模型中的字段名,等等。
Entry.objects.order_by(‘blog__name‘, ‘headline‘)
如果您嘗試按與另一個模型相關的字段排序,Django將在相關模型上使用默認的順序,如果沒有元數據,則使用相關模型的主鍵排序。指定排序。
例如,由於博客模型沒有指定默認的排序
Entry.objects.order_by(‘blog‘) 等同於 Entry.objects.order_by(‘blog__id‘)
如果博客模型指定排序 ordering = [‘name‘]
Entry.objects.order_by(‘blog__id‘)
如果不希望對查詢應用任何排序,甚至不希望對默認排序應用任何排序,那麽可以不帶參數地調用order_by()。
可以通過檢查QuerySet來判斷查詢是否有序。有序屬性,如果查詢集以任何方式被排序,則該屬性為True。
每個order_by()調用將清除以前的任何排序。例如,該查詢將按pub_date排序,而不是按標題
Entry.objects.order_by("headline").order_by("-pub_date”)
(5)reverse():排序後的結果順序反轉(必須是已經排好序的結果集)
取出最後五個對象
my_queryset.reverse()[:5]
與序列的分片[-5:]不一樣,分片首先看到的是倒數第五個,reverse首先看到的是最後一個。
Django不支持這種訪問模式(從末尾開始分段),因為在SQL中不可能有效地做到這一點。
(6)dictinct():返回一個新的QuerySet,它在SQL查詢中使用SELECT DISTINCT。這從查詢結果中消除了重復的行。
Author.objects.distinct()
(7)values():返回一個QuerySet,當作為叠代使用時,它返回字典而不是模型實例。這些字典中的每一個都代表一個對象,其鍵對應於模型對象的屬性名。
位置參數指定需要在select中查詢的值。values()方法還接受可選的關鍵字參數,這些參數傳遞給annotate():
>>> Blog.objects.filter(name__startswith=‘Beatles‘).values() <QuerySet [{‘id‘: 1, ‘name‘: ‘Beatles Blog‘, ‘tagline‘: ‘All the latest Beatles news.‘}]>
>>> Blog.objects.values(‘id‘, ‘name‘)
<QuerySet [{‘id‘: 1, ‘name‘: ‘Beatles Blog‘}]>
>>> from django.db.models.functions import Lower
>>> Blog.objects.values(lower_name=Lower(‘name‘))
<QuerySet [{‘lower_name‘: ‘beatles blog‘}]>
在values()子句中的其他參數之前應用values()子句中的聚合。如果需要按另一個值進行分組,則將其添加到前面的values()子句中。
>>> from django.db.models import Count >>> Blog.objects.values(‘entry__authors‘, entries=Count(‘entry‘)) <QuerySet [{‘entry__authors‘: 1, ‘entries‘: 20}, {‘entry__authors‘: 1, ‘entries‘: 13}]> >>> Blog.objects.values(‘entry__authors‘).annotate(entries=Count(‘entry‘)) <QuerySet [{‘entry__authors‘: 1, ‘entries‘: 33}]>
如果有一個名為foo的字段是ForeignKey,那麽默認值()調用將返回一個名為foo_id的字典鍵,因為這是存儲實際值的隱藏模型屬性的名稱(foo屬性引用相關模型)。
當您調用values()並傳入字段名時,您可以傳入foo或foo_id,您將得到相同的結果(dictionary鍵將匹配您傳入的字段名)。
>>> Entry.objects.values() <QuerySet [{‘blog_id‘: 1, ‘headline‘: ‘First Entry‘, ...}, ...]> >>> Entry.objects.values(‘blog‘) <QuerySet [{‘blog‘: 1}, ...]> >>> Entry.objects.values(‘blog_id‘) <QuerySet [{‘blog_id‘: 1}, ...]>
最後,註意,您可以在values()調用之後調用filter()、order_by()等,這意味著這兩個調用是相同的
Blog.objects.values().order_by(‘id‘) Blog.objects.order_by(‘id‘).values()
(8):value_list():返回元組而不是字典,如果只在單個字段中傳遞,也可以傳遞平面參數。如果為真,這將意味著返回的結果是單個值,
而不是一個元組。多與兩個字段是不要傳遞flat參數,一個例子應該可以使區別變得更清楚:
>>> Entry.objects.values_list(‘id‘).order_by(‘id‘) <QuerySet[(1,), (2,), (3,), ...]> >>> Entry.objects.values_list(‘id‘, flat=True).order_by(‘id‘) <QuerySet [1, 2, 3, ...]>
傳遞named=True,獲得命名元組(Django 2.0新增)
>>> Entry.objects.values_list(‘id‘, ‘headline‘, named=True) <QuerySet [Row(id=1, headline=‘First entry‘), ...]>
從查詢的結果集中獲取指定條件的對象
>>> Entry.objects.values_list(‘headline‘, flat=True).get(pk=1) ‘First entry‘
(9)none():創建一個空的查詢集,EmptyQuerySet的子集
(10)all():返回所有結果
(11)union():兩個結果集的並集
intersection():兩個結果集的交集
difference():兩個屆國際的差集
(12)selected_related():預先查詢外鍵關系。查詢略復雜,但是使用外鍵時不需要再次訪問數據庫
select_related工作方式是創建SQL連接,並在SELECT語句中包含相關對象的字段。因此,select_related獲取相同數據庫查詢中的相關對象。
然而,為了避免由於跨“多”關系連接而導致更大的結果集,select_related僅限於單值關系——外鍵和一對一關系。
# Hits the database. e = Entry.objects.get(id=5) # Hits the database again to get the related Blog object. b = e.blog # Hits the database. e = Entry.objects.select_related(‘blog‘).get(id=5) # Doesn‘t hit the database, because e.blog has been prepopulated # in the previous query. b = e.blog
(13)prefetch_releated():返回一個QuerySet,它將在單個批處理中為每個指定查找自動檢索相關對象。
prefetch_related為每個關系執行單獨的查找,並在Python中執行“連接”。這允許它預取多對多和多對一對象,這是不能使用select_related實現的,
除了select_related支持的外鍵和一對一關系之外。它還支持GenericRelation和GenericForeignKey的預抓取,但是,它必須被限制為同構的結果集。
例如,只在查詢限制為一個ContentType時才支持GenericForeignKey引用的預抓取對象。具體請查閱Django官網。
(14)defer():延遲加載
在一些復雜的數據建模情況下,您的模型可能包含許多字段,其中一些可能包含許多數據(例如文本字段),或者需要昂貴的處理才能將它們轉換為Python對象。
如果在最初獲取數據時不知道是否需要這些特定字段的情況下使用queryset的結果,那麽可以告訴Django不要從數據庫中檢索它們。
這是通過傳遞字段的名稱來完成的,以便不加載以延遲()
Entry.objects.defer("headline", "body")
如果您想清除延遲字段的集合,請將None作為參數傳遞給defer()
(15)only():惟一的()方法或多或少與defer()相反。使用在檢索模型時不應該延遲的字段調用它。如果您有一個模型,其中幾乎所有字段都需要延遲,
那麽使用only()來指定補充字段集可以得到更簡單的代碼。無論何時調用only(),它都會替換要立即加載的字段集。因此,連續調用only()只會導致只考慮最後的字段
(16)raw():獲取原始SQL查詢,執行它,並返回django.db.models.query。RawQuerySet實例。這個RawQuerySet實例可以像普通的QuerySet一樣遍歷,以提供對象實例。
2、返回新查詢結果集的操作
(1)AND(&)組合的查詢集必須使用兩個相同的模型
Model.objects.filter(x=1) & Model.objects.filter(y=2) Model.objects.filter(x=1, y=2) from django.db.models import Q Model.objects.filter(Q(x=1) & Q(y=2))
SELECT ... WHERE x=1 AND y=2
(2)OR(|)
Model.objects.filter(x=1) | Model.objects.filter(y=2) from django.db.models import Q Model.objects.filter(Q(x=1) | Q(y=2))
SELECT ... WHERE x=1 OR y=2
3、不返回查詢集的方法
(1)get() :返回匹配給定查找參數的對象,查找參數的格式應與字段查找中描述的格式相同。
返回一個以上對象時引起MUultipleObjectReturned異常
返回為空時引起ObjectDoesNotExist異常
(2)create():創建一個對象並保存,等價於實例化一個模型,載調用save方法
(3)get_or_create(defaults=None,**kwargs):查找或創建,返回一個元組(對象,已創建),其中對象是檢索的或已創建的對象,並創建一個布爾值,指定是否創建了新對象。
傳遞給get_or_create()的任何關鍵字參數——除了一個可選的稱為默認值的參數——將在get()調用中使用。如果找到一個對象,get_or_create()將返回該對象的一個元組,
並返回False。如果找到多個對象,get_or_create()會引發返回的multipleobjectsreturn。如果沒有找到對象,get_or_create()將實例化並保存一個新對象,返回新對象和True的元組。
obj, created = Person.objects.get_or_create( first_name=‘John‘, last_name=‘Lennon‘, defaults={‘birthday‘: date(1940, 10, 9)}, )
(4)update_or_create(defaults=None,**kwargs):更新或創建。返回一個元組(對象,已創建),其中對象是已創建或更新的對象,並創建一個布爾值,指定是否創建了新對象
obj, created = Person.objects.update_or_create( first_name=‘John‘, last_name=‘Lennon‘, defaults={‘first_name‘: ‘Bob‘}, )
(5)count():返回一個整數,該整數表示數據庫中與QuerySet匹配的對象的數量。
(6)iterator(chunk_size=2000):放回一個叠代器,對於數據量大的結果集,顯著地減少內存消耗。註意,在已經求值的QuerySet上使用iterator()將迫使它再次求值,重復查詢。chunk_size參數控制
從數據庫驅動程序檢索的批處理的大小。較大的批處理減少了與數據庫驅動程序通信的開銷,而內存消耗則略有增加。
(7)latest():根據數據字段返回最新的結果,還可以根據幾個字段選擇最新的。例如,當兩個條目有相同的pub_date時,選擇最早的expire_date條目:
earlist():返回最早的結果
Entry.objects.latest(‘pub_date‘, ‘-expire_date‘)
(8)first():返回由queryset匹配的第一個對象,如果沒有匹配的對象,則返回None。如果QuerySet沒有定義任何排序,那麽QuerySet將由主鍵自動排序。
last():返回最後一個結果。
(9)aggregate():聚合查詢,可以通過使用關鍵字參數指定聚合函數,您可以控制返回的聚合值的名稱。
>>> from django.db.models import Count >>> q = Blog.objects.aggregate(Count(‘entry‘)) {‘entry__count‘: 16}
q = Blog.objects.aggregate(number_of_entries=Count(‘entry‘))
{‘number_of_entries‘: 16}
(10)exists():是否存在。如果QuerySet包含任何結果,返回True;如果不包含結果,返回False。嘗試以盡可能簡單和最快的方式執行查詢,但它執行的查詢與
普通的QuerySet查詢幾乎相同。
(11)update(**kwargs):更新對象,對指定的字段執行SQL update查詢,並返回匹配的行數(如果某些行已經具有新值,則可能不等於更新的行數)。
只能更新主表中的列,不能更新外鍵的表的列
(12)delete():刪除對象,對QuerySet中的所有行執行SQL delete查詢,並返回被刪除的對象數量和每個對象類型的刪除數量字典。
Django QuestSet API (官方文檔)