Yanıtlar:
Bunu yapmanın 'yerleşik' yolu yoktur. Django, her seferinde DoesNotExist istisnasını yükseltir. Bunu python'da işlemenin deyimsel yolu onu bir deneme yakalamaya sarmaktır:
try:
go = SomeModel.objects.get(foo='bar')
except SomeModel.DoesNotExist:
go = None
Yaptığım şey, alt sınıfları safe_get
modellemektir. Yönetici, yukarıdaki kodu benzer bir şekilde oluşturun ve modellerim için bu yöneticiyi kullanın. Yazabilirsiniz Bu şekilde: SomeModel.objects.safe_get(foo='bar')
.
SomeModel.objects.filter(foo='bar').first()
bu ilk eşleşmeyi veya Hiçbiri'ni kullanabilirsiniz. queryset.get()
filter().first()
, istisnanın gidilecek yol olduğunu düşünüyorum.
Django 1.6'dan beri first () yöntemini şu şekilde kullanabilirsiniz :
Content.objects.filter(name="baby").first()
get()
DoesNotExist
verilen parametreler için bir nesne bulunamazsa bir istisna oluşturur. Bu istisna aynı zamanda model sınıfının bir özelliğidir.DoesNotExist
Dan istisna devralırdjango.core.exceptions.ObjectDoesNotExist
İstisnayı yakalayabilir ve None
gitmek için atayabilirsiniz .
from django.core.exceptions import ObjectDoesNotExist
try:
go = Content.objects.get(name="baby")
except ObjectDoesNotExist:
go = None
Bunun için genel bir fonksiyon oluşturabilirsiniz.
def get_or_none(classmodel, **kwargs):
try:
return classmodel.objects.get(**kwargs)
except classmodel.DoesNotExist:
return None
Bunu aşağıdaki gibi kullanın:
go = get_or_none(Content,name="baby")
İçerik girişi eşleşmeyen başka bir girdi döndürülmezse Git Yok olur.
Not: name = "baby" için birden fazla giriş döndürüldüğünde, ÇokluObjectsReturned istisnasını yükseltir
Bunu şu şekilde yapabilirsiniz:
go = Content.objects.filter(name="baby").first()
Şimdi go değişkeni istediğiniz nesne veya Yok olabilir
Ref: https://docs.djangoproject.com/tr/1.8/ref/models/querysets/#django.db.models.query.QuerySet.first
İşleri kolaylaştırmak için, burada harika yanıtlardan gelen girdilere dayanarak yazdığım kodun bir parçası:
class MyManager(models.Manager):
def get_or_none(self, **kwargs):
try:
return self.get(**kwargs)
except ObjectDoesNotExist:
return None
Ve sonra modelinizde:
class MyModel(models.Model):
objects = MyManager()
Bu kadar. Şimdi MyModel.objects.get () ve MyModel.objetcs.get_or_none ()
exists
bir filtreyle kullanabilirsiniz :
Content.objects.filter(name="baby").exists()
#returns False or True depending on if there is anything in the QS
sadece var olup olmadığını bilmek istiyorsanız
exists()
ile birlikte kullanılacaktır, if
böylece db'ye iki kez çarpılır. Başka birine yardım etmesi durumunda yorumu hala saklayacağım.
Görünümlerinizdeki farklı noktalardaki istisnaları işlemek gerçekten zahmetli olabilir .. models.py dosyasında özel bir Model Yöneticisi tanımlamaya ne dersiniz?
class ContentManager(model.Manager):
def get_nicely(self, **kwargs):
try:
return self.get(kwargs)
except(KeyError, Content.DoesNotExist):
return None
ve sonra bunu içerik Model sınıfına dahil etme
class Content(model.Model):
...
objects = ContentManager()
Bu şekilde görüşlerde kolayca ele alınabilir yani
post = Content.objects.get_nicely(pk = 1)
if post:
# Do something
else:
# This post doesn't exist
return self.get(**kwargs)
benim için çalışmasını sağlayacak bir not bırakmak istedim. Cevabı yanlış olan bir şey söylememek, sadece daha sonraki sürümlerle (veya benim için çalışmasını engelleyen herhangi bir şeyle) kullanmaya çalışan herkes için bir ipucu.
Yeniden uygulamak istemeyebileceğiniz can sıkıcı işlevlerden biridir :
from annoying.functions import get_object_or_None
#...
user = get_object_or_None(Content, name="baby")
get_object_or_None
ama MultipleObjectsReturned
birden fazla nesne varsa hala yükseldiğini buldum . Bu nedenle, kullanıcı bir çevreyle try-except
(işlevin kendisinin try-except
zaten sahip olduğu) düşünebilir .
Bence kullanmak kötü bir fikir değil 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)
Bu örnek şuna eşdeğerdir:
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 çevrimiçi belgelerinde get_object_or_404 () hakkında daha fazla bilgi edinebilirsiniz .
Django 1.7'den itibaren şunları yapabilirsiniz:
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 ()" avantajı, aşağıdakilerin her ikisinin de çalışmasıdır:
MyModel.objects.filter(...).get_or_none()
MyModel.objects.get_or_none()
Burada QuerySet
, benzersiz nesneyi (varsa), modelin all
nesneleri sorgulama kümesinden (örneğin, üst örnek):
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
Bu iki şekilde kullanılabilir, örneğin:
obj = get_unique_or_none(Model, **kwargs)
daha önce tartışıldığı gibiobj = get_unique_or_none(Model, parent.children, **kwargs)
İstisnasız:
if SomeModel.objects.filter(foo='bar').exists():
x = SomeModel.objects.get(foo='bar')
else:
x = None
İstisna kullanma:
try:
x = SomeModel.objects.get(foo='bar')
except SomeModel.DoesNotExist:
x = None
Python'da ne zaman istisna kullanılması gerektiğine dair biraz tartışma var. Bir yandan, "bağış istemek izin vermekten daha kolaydır". Buna katılıyorum, ancak bir istisnanın kalması gerektiğine inanıyorum, istisna ve "ideal dava" bir tanesine çarpmadan çalışmalıdır.
Olarak adlandırılan modellere eklenen Django yerleşik istisnasını kullanabiliriz .DoesNotExist
. Yani, ObjectDoesNotExist
istisna ithal etmek zorunda değiliz .
Bunun yerine:
from django.core.exceptions import ObjectDoesNotExist
try:
content = Content.objects.get(name="baby")
except ObjectDoesNotExist:
content = None
Bunu yapabiliriz:
try:
content = Content.objects.get(name="baby")
except Content.DoesNotExist:
content = None
Bu, yöntemin Yok değerini döndürmesi dışında, Django'nun get_object_or_404 ürününden bir taklitçi. Bu, only()
yalnızca belirli alanları almak için sorgu kullanmamız gerektiğinde son derece yararlıdır . Bu yöntem bir modeli veya bir sorgu kümesini kabul edebilir.
from django.shortcuts import _get_queryset
def get_object_or_none(klass, *args, **kwargs):
"""
Use get() to return an object, or return None if object
does not exist.
klass may be a Model, Manager, or QuerySet object. All other passed
arguments and keyword arguments are used in the get() query.
Like with QuerySet.get(), MultipleObjectsReturned is raised if more than
one object is found.
"""
queryset = _get_queryset(klass)
if not hasattr(queryset, 'get'):
klass__name = klass.__name__ if isinstance(klass, type) else klass.__class__.__name__
raise ValueError(
"First argument to get_object_or_none() must be a Model, Manager, "
"or QuerySet, not '%s'." % klass__name
)
try:
return queryset.get(*args, **kwargs)
except queryset.model.DoesNotExist:
return None
Belki daha iyidir:
User.objects.filter(username=admin_username).exists()