當前位置: 首頁>>代碼示例 >>用法及示例精選 >>正文


Python Django QuerySet.get_or_create用法及代碼示例


本文介紹 django.db.models.query.QuerySet.get_or_create 的用法。

聲明

get_or_create(defaults=None, **kwargs)

一種使用給定 kwargs 查找對象的便捷方法(如果您的模型具有所有字段的默認值,則可能為空),如有必要,創建一個。

返回 (object, created) 的元組,其中 object 是檢索或創建的對象, created 是指定是否創建新對象的布爾值。

這是為了防止在並行發出請求時創建重複的對象,並作為樣板代碼的快捷方式。例如:

try:
    obj = Person.objects.get(first_name='John', last_name='Lennon')
except Person.DoesNotExist:
    obj = Person(first_name='John', last_name='Lennon', birthday=date(1940, 10, 9))
    obj.save()

在這裏,對於並發請求,可能會多次嘗試保存具有相同參數的Person。為了避免這種競爭條件,可以使用get_or_create() 重寫上麵的示例,如下所示:

obj, created = Person.objects.get_or_create(
    first_name='John',
    last_name='Lennon',
    defaults={'birthday': date(1940, 10, 9)},
)

任何傳遞給 get_or_create() 的關鍵字參數——except 一個可選的 defaults——都將在 get() 調用中使用。如果找到一個對象,get_or_create() 返回該對象和 False 的元組。

警告

假設數據庫強製關鍵字參數的唯一性(請參閱 unique unique_together ),此方法是原子的。如果關鍵字參數中使用的字段沒有唯一性約束,則對該方法的並發調用可能會導致插入具有相同參數的多行。

您可以通過將 get_or_create()filter() 鏈接並使用 Q objects 來為檢索到的對象指定更複雜的條件。例如,檢索 Robert 或 Bob Marley(如果存在),否則創建後者:

from django.db.models import Q

obj, created = Person.objects.filter(
    Q(first_name='Bob') | Q(first_name='Robert'),
).get_or_create(last_name='Marley', defaults={'first_name': 'Bob'})

如果找到多個對象,則 get_or_create() 引發 MultipleObjectsReturned 。如果找到一個對象 notget_or_create() 將實例化並保存一個新對象,返回一個新對象和 True 的元組。新對象將大致按照以下算法創建:

params = {k: v for k, v in kwargs.items() if '__' not in k}
params.update({k: v() if callable(v) else v for k, v in defaults.items()})
obj = self.model(**params)
obj.save()

在英語中,這意味著以任何不包含雙下劃線的非 'defaults' 關鍵字參數開頭(這將指示不精確的查找)。然後添加 defaults 的內容,必要時覆蓋任何鍵,並將結果用作模型類的關鍵字參數。如果 defaults 中有任何可調用對象,請評估它們。正如上麵所暗示的,這是所使用算法的簡化,但它包含所有相關的細節。內部實現有比這更多的error-checking,並處理一些額外的edge-conditions;如果您有興趣,請閱讀代碼。

如果您有一個名為 defaults 的字段並希望將其用作 get_or_create() 中的精確查找,請使用 'defaults__exact' ,如下所示:

Foo.objects.get_or_create(defaults__exact='bar', defaults={'defaults': 'baz'})

當您使用手動指定的主鍵時,get_or_create() 方法的錯誤行為與 create() 相似。如果需要創建對象並且數據庫中已存在 key ,則會引發 IntegrityError

最後,關於使用的一句話get_or_create()在 Django 視圖中。請確保僅在POST請求,除非您有充分的理由不這樣做。GET請求不應該對數據產生任何影響。相反,使用POST每當對頁麵的請求對您的數據產生副作用時。有關更多信息,請參閱安全方法在 HTTP 規範中。

警告

您可以使用get_or_create() ManyToManyField 屬性和反向關係。在這種情況下,您將在該關係的上下文中限製查詢。如果您不始終如一地使用它,這可能會導致您出現一些完整性問題。

為以下型號:

class Chapter(models.Model):
    title = models.CharField(max_length=255, unique=True)

class Book(models.Model):
    title = models.CharField(max_length=256)
    chapters = models.ManyToManyField(Chapter)

您可以通過 Book 的 chapters 字段使用get_or_create(),但它隻在該書的上下文中獲取:

>>> book = Book.objects.create(title="Ulysses")
>>> book.chapters.get_or_create(title="Telemachus")
(<Chapter: Telemachus>, True)
>>> book.chapters.get_or_create(title="Telemachus")
(<Chapter: Telemachus>, False)
>>> Chapter.objects.create(title="Chapter 1")
<Chapter: Chapter 1>
>>> book.chapters.get_or_create(title="Chapter 1")
# Raises IntegrityError

發生這種情況是因為它試圖通過書 “Ulysses” 獲取或創建“第 1 章”,但它無法執行任何操作:關係無法獲取該章,因為它與該書無關,但是它也無法創建它,因為title 字段應該是唯一的。

相關用法


注:本文由純淨天空篩選整理自djangoproject.com大神的英文原創作品 django.db.models.query.QuerySet.get_or_create。非經特殊聲明,原始代碼版權歸原作者所有,本譯文未經允許或授權,請勿轉載或複製。