1. 程式人生 > >Django QuestSet API (官方文檔)

Django QuestSet API (官方文檔)

ren 屬性 adl bec 下劃線 指定字段 排序 排列 function

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_entries
42 # 指定關鍵字參數,聚合別名為關鍵字參數

  (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 (官方文檔)