當我要求模型管理器獲取對象時,如果沒有匹配的對象,則會提升DoesNotExist
。如果存在該對象,該如何獲取;如果該對象不存在,該如何獲取?
go = Content.objects.get(name="baby")
代替DoesNotExist
,我怎麼能有go
是None
呢?
當我要求模型管理器獲取對象時,如果沒有匹配的對象,則會提升DoesNotExist
。如果存在該對象,該如何獲取;如果該對象不存在,該如何獲取?
go = Content.objects.get(name="baby")
代替DoesNotExist
,我怎麼能有go
是None
呢?
沒有「內置」的方式來做到這一點。 Django每次都會引發DoesNotExist異常。 在Python來處理這種情況慣用的辦法是將它包裝在一個嘗試捕捉:
try:
go = SomeModel.objects.get(foo='bar')
except SomeModel.DoesNotExist:
go = None
我沒做什麼,就是要繼承models.Manager,創建safe_get
像上面的代碼,並使用該經理爲我的楷模。這樣你可以寫:SomeModel.objects.safe_get(foo='bar')
。
get()
如果對象未找到對於給定的參數提出了DoesNotExist
異常。這個異常也是模型類的一個屬性。該DoesNotExist
例外繼承django.core.exceptions.ObjectDoesNotExist
您可以捕獲該異常,並分配None
去。
from django.core.exceptions import ObjectDoesNotExist
try:
go = Content.objects.get(name="baby")
except ObjectDoesNotExist:
go = None
您可以爲此創建一個通用函數。
def get_or_none(classmodel, **kwargs):
try:
return classmodel.objects.get(**kwargs)
except classmodel.DoesNotExist:
return None
使用此象下面這樣:
go = get_or_none(Content,name="baby")
去將無如果沒有條目匹配否則將返回內容條目。
注:這將引發異常MultipleObjectsReturned如果超過一個條目返回的名稱=「寶貝」在你的意見不同點
處理異常真會是如何定義自定義模型管理器cumbersome..What,在models.py文件,像
class ContentManager(model.Manager):
def get_nicely(self, **kwargs):
try:
return self.get(kwargs)
except(KeyError, Content.DoesNotExist):
return None
,然後把它放置在內容模型類
class Content(model.Model):
...
objects = ContentManager()
通過這種方式也可以是EAS隨手處理的意見,即
post = Content.objects.get_nicely(pk = 1)
if post:
# Do something
else:
# This post doesn't exist
我真的很喜歡這個解決方案,但無法讓它工作就像在使用python 3.6時一樣。想要留下一個說明,即修改ContentManager中的返回值爲'return self.get(** kwargs)'讓它爲我工作。不要說任何關於答案的錯誤,只是對於任何人試圖在更高版本中使用它的提示(或者其他任何使它不能爲我工作的提示)。 – skagzilla
爲了方便起見,這裏是我寫的代碼,根據輸入從精彩回帖這裏的一個片段:
class MyManager(models.Manager):
def get_or_none(self, **kwargs):
try:
return self.get(**kwargs)
except ObjectDoesNotExist:
return None
然後在你的模型:
class MyModel(models.Model):
objects = MyManager()
就是這樣。 現在你有MyModel.objects.get()以及MyModel.objetcs。get_or_none()
另外,不要忘記從django.core.exceptions導入: import ObjectDoesNotExist –
你可以使用exists
帶有過濾器:
Content.objects.filter(name="baby").exists()
#returns False or True depending on if there is anything in the QS
只是如果你只是想知道,如果它存在
這會在存在時導致額外的數據庫調用。不是一個好主意 – Christoffer
這裏有輔助功能,可以讓你的變化替代如果您希望從除模型的all
對象查詢集(例如,來自屬於父實例的子項子集的子集)以外的查詢集獲取唯一對象(如果存在),則可以傳入QuerySet
實例:
def get_unique_or_none(model, queryset=None, **kwargs):
"""
Performs the query on the specified `queryset`
(defaulting to the `all` queryset of the `model`'s default manager)
and returns the unique object matching the given
keyword arguments. Returns `None` if no match is found.
Throws a `model.MultipleObjectsReturned` exception
if more than one match is found.
"""
if queryset is None:
queryset = model.objects.all()
try:
return queryset.get(**kwargs)
except model.DoesNotExist:
return None
這可以以兩種方式使用,例如:
obj = get_unique_or_none(Model, **kwargs)
如previosuly討論obj = get_unique_or_none(Model, parent.children, **kwargs)
我發現'django煩人'已經處理了這種情況。 – Gary
由於django的1.6可以使用像first()方法,以便:
Content.objects.filter(name="baby").first()
在這種情況下,如果有多個匹配項,則不會引發錯誤。 –
我喜歡這個解決方案,因爲使用'objecst.get()'推斷我們知道數據庫中有一個或沒有。 – EmptyFlash
'FeroxTL'你需要爲這個答案寫信@guettli,正如他在你發佈前一年接受的答案中所評論的那樣。 – colminator
毫無例外:
if SomeModel.objects.filter(foo='bar').exists():
x = SomeModel.objects.get(foo='bar')
else:
x = None
使用一個例外:
try:
x = SomeModel.objects.get(foo='bar')
except SomeModel.DoesNotExist:
x = None
有一個關於何時應該在Python中使用的異常位的說法。一方面,「請求原諒比獲得許可要容易」。雖然我同意這一點,但我認爲應該保留一個例外,那就是例外,「理想情況」應該運行而不會觸及一個例外。
從Django中1.7起,你可以這樣做:
class MyQuerySet(models.QuerySet):
def get_or_none(self, **kwargs):
try:
return self.get(**kwargs)
except self.model.DoesNotExist:
return None
class MyBaseModel(models.Model):
objects = MyQuerySet.as_manager()
class MyModel(MyBaseModel):
...
class AnotherMyModel(MyBaseModel):
...
的優勢 「MyQuerySet.as_manager()」 是兩個以下將工作:
MyModel.objects.filter(...).get_or_none()
MyModel.objects.get_or_none()
這是其中之一annoying functions你可能不想重新執行:
from annoying.functions import get_object_or_None
#...
user = get_object_or_None(Content, name="baby")
我們可以使用Django內建的異常,它是一個連接到名爲.DoesNotExist
的型號。所以,我們不必導入ObjectDoesNotExist
異常。
而不是做:
from django.core.exceptions import ObjectDoesNotExist
try:
content = Content.objects.get(name="baby")
except ObjectDoesNotExist:
content = None
我們可以這樣做:
try:
content = Content.objects.get(name="baby")
except Content.DoesNotExist:
content = None
你可以這樣來做:
go = Content.objects.filter(name="baby").first()
現在去變量可以是任何你想要的對象或無
編號:https://docs.djangoproject.com/en/1.8/ref/models/querysets/#django.db.models.query.QuerySet.first
如果你想要一個簡單的單行的解決方案,不涉及異常處理,條件語句或1.6或更高版本的Django的要求,而是執行此操作:
x = next(iter(SomeModel.objects.filter(foo='bar')), None)
,我認爲它不是「T壞主意使用get_object_or_404()
from django.shortcuts import get_object_or_404
def my_view(request):
my_object = get_object_or_404(MyModel, pk=1)
這個例子是等價於:
from django.http import Http404
def my_view(request):
try:
my_object = MyModel.objects.get(pk=1)
except MyModel.DoesNotExist:
raise Http404("No MyModel matches the given query.")
您可以在django在線文檔中閱讀更多關於get_object_or_404()。
+1用於捕獲特定的異常。 –
很好地使用SomeModel.DoesNotExist,而不是導入異常。 – Symmitchry
該解決方案長四行。對我來說這太多了。使用django 1.6,你可以使用'SomeModel.objects.filter(foo ='bar')。first()'這會返回第一個匹配,或者返回None。它不會失敗,如果有'queryset.get()' – guettli