本文介紹 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()
鏈接並使用
來為檢索到的對象指定更複雜的條件。例如,檢索 Robert 或 Bob Marley(如果存在),否則創建後者:Q objects
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
not
,get_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()
方法的錯誤行為與
相似。如果需要創建對象並且數據庫中已存在 key ,則會引發 create()
。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
字段應該是唯一的。
相關用法
- Python Django QuerySet.get用法及代碼示例
- Python Django QuerySet.select_related用法及代碼示例
- Python Django QuerySet.union用法及代碼示例
- Python Django QuerySet.latest用法及代碼示例
- Python Django QuerySet.values用法及代碼示例
- Python Django QuerySet.intersection用法及代碼示例
- Python Django QuerySet.none用法及代碼示例
- Python Django QuerySet.exclude用法及代碼示例
- Python Django QuerySet.update_or_create用法及代碼示例
- Python Django QuerySet.prefetch_related用法及代碼示例
- Python Django QuerySet.first用法及代碼示例
- Python Django QuerySet.annotate用法及代碼示例
- Python Django QuerySet.dates用法及代碼示例
- Python Django QuerySet.values_list用法及代碼示例
- Python Django QuerySet.select_for_update用法及代碼示例
- Python Django QuerySet.order_by用法及代碼示例
- Python Django QuerySet.bulk_update用法及代碼示例
- Python Django QuerySet.in_bulk用法及代碼示例
- Python Django QuerySet.defer用法及代碼示例
- Python Django QuerySet.aggregate用法及代碼示例
- Python Django QuerySet.reverse用法及代碼示例
- Python Django QuerySet.count用法及代碼示例
- Python Django QuerySet.exists用法及代碼示例
- Python Django QuerySet.explain用法及代碼示例
- Python Django QuerySet.create用法及代碼示例
注:本文由純淨天空篩選整理自djangoproject.com大神的英文原創作品 django.db.models.query.QuerySet.get_or_create。非經特殊聲明,原始代碼版權歸原作者所有,本譯文未經允許或授權,請勿轉載或複製。