Jawaban:
Tidak ada cara 'bawaan' untuk melakukan ini. Django akan memunculkan exception DoesNotExist setiap saat. Cara idiomatis untuk menangani ini dengan python adalah membungkusnya dengan try catch:
try:
go = SomeModel.objects.get(foo='bar')
except SomeModel.DoesNotExist:
go = None
Apa yang saya lakukan adalah membuat subclass models.Manager, buat safe_get
kode seperti di atas dan gunakan manajer itu untuk model saya. Dengan cara itu Anda dapat menulis: SomeModel.objects.safe_get(foo='bar')
.
SomeModel.objects.filter(foo='bar').first()
ini mengembalikan pertandingan pertama, atau Tidak Ada. Tidak gagal jika ada beberapa contoh sepertiqueryset.get()
filter().first()
saya pikir pengecualian adalah cara untuk pergi.
Sejak django 1.6 Anda dapat menggunakan metode first () seperti:
Content.objects.filter(name="baby").first()
get()
memunculkanDoesNotExist
eksepsi jika suatu objek tidak ditemukan untuk parameter yang diberikan. Pengecualian ini juga merupakan atribut dari kelas model. TheDoesNotExist
pengecualian mewarisi daridjango.core.exceptions.ObjectDoesNotExist
Anda dapat menangkap pengecualian dan menetapkan None
untuk pergi.
from django.core.exceptions import ObjectDoesNotExist
try:
go = Content.objects.get(name="baby")
except ObjectDoesNotExist:
go = None
Anda dapat membuat fungsi generik untuk ini.
def get_or_none(classmodel, **kwargs):
try:
return classmodel.objects.get(**kwargs)
except classmodel.DoesNotExist:
return None
Gunakan ini seperti di bawah ini:
go = get_or_none(Content,name="baby")
go akan menjadi None jika tidak ada entri yang cocok dengan yang lain akan mengembalikan entri Konten.
Catatan: Ini akan memunculkan pengecualian MultipleObjectsReturned jika lebih dari satu entri dikembalikan untuk name = "baby"
Anda bisa melakukannya dengan cara ini:
go = Content.objects.filter(name="baby").first()
Variabel go sekarang bisa berupa objek yang Anda inginkan atau Tidak Ada
Ref: https://docs.djangoproject.com/en/1.8/ref/models/querysets/#django.db.models.query.QuerySet.first
Untuk mempermudah, berikut cuplikan kode yang saya tulis, berdasarkan masukan dari balasan yang indah di sini:
class MyManager(models.Manager):
def get_or_none(self, **kwargs):
try:
return self.get(**kwargs)
except ObjectDoesNotExist:
return None
Dan kemudian dalam model Anda:
class MyModel(models.Model):
objects = MyManager()
Itu dia. Sekarang Anda memiliki MyModel.objects.get () serta MyModel.objetcs.get_or_none ()
Anda dapat menggunakan exists
dengan filter:
Content.objects.filter(name="baby").exists()
#returns False or True depending on if there is anything in the QS
hanya alternatif untuk jika Anda hanya ingin tahu apakah itu ada
exists()
akan digunakan dengan if
klausa sebelum mengambil objek sehingga menyebabkan pukulan ganda ke db. Saya akan tetap menyimpan komentar kalau-kalau itu membantu orang lain.
Menangani pengecualian pada titik yang berbeda dalam tampilan Anda bisa sangat merepotkan..Bagaimana dengan mendefinisikan Manajer Model kustom, dalam file models.py, seperti
class ContentManager(model.Manager):
def get_nicely(self, **kwargs):
try:
return self.get(kwargs)
except(KeyError, Content.DoesNotExist):
return None
dan kemudian memasukkannya ke dalam kelas Model konten
class Content(model.Model):
...
objects = ContentManager()
Dengan cara ini dapat dengan mudah ditangani dalam pandangan yaitu
post = Content.objects.get_nicely(pk = 1)
if post:
# Do something
else:
# This post doesn't exist
return self.get(**kwargs)
agar berfungsi untuk saya. Bukan untuk mengatakan ada yang salah dengan jawabannya, hanya tip bagi siapa pun yang mencoba menggunakannya dengan versi yang lebih baru (atau dengan apa pun yang membuatnya tidak bekerja untuk saya).
Ini salah satu fungsi menjengkelkan yang mungkin tidak ingin Anda laksanakan kembali:
from annoying.functions import get_object_or_None
#...
user = get_object_or_None(Content, name="baby")
get_object_or_None
tetapi ternyata masih naik MultipleObjectsReturned
jika lebih dari satu objek. Jadi, pengguna mungkin mempertimbangkan untuk mengelilinginya dengan try-except
(yang fungsinya sendiri try-except
sudah ada).
Saya pikir itu bukan ide yang buruk untuk digunakan 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)
Contoh ini setara dengan:
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.")
Anda dapat membaca lebih lanjut tentang get_object_or_404 () di dokumentasi online Django.
Dari django 1.7 dan selanjutnya Anda dapat melakukan seperti:
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):
...
Keuntungan dari "MyQuerySet.as_manager ()" adalah bahwa kedua hal berikut ini akan berfungsi:
MyModel.objects.filter(...).get_or_none()
MyModel.objects.get_or_none()
Berikut adalah variasi pada fungsi helper yang memungkinkan Anda untuk secara opsional mengirimkan QuerySet
contoh, jika Anda ingin mendapatkan objek unik (jika ada) dari queryset selain model all
objek queryset (misalnya dari subset item anak yang dimiliki oleh sebuah instance induk):
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
Ini dapat digunakan dalam dua cara, misalnya:
obj = get_unique_or_none(Model, **kwargs)
seperti yang telah dibahas sebelumnyaobj = get_unique_or_none(Model, parent.children, **kwargs)
Tanpa pengecualian:
if SomeModel.objects.filter(foo='bar').exists():
x = SomeModel.objects.get(foo='bar')
else:
x = None
Menggunakan pengecualian:
try:
x = SomeModel.objects.get(foo='bar')
except SomeModel.DoesNotExist:
x = None
Ada sedikit argumen tentang kapan seseorang harus menggunakan pengecualian dalam python. Di satu sisi, "lebih mudah untuk meminta maaf daripada izin". Sementara saya setuju dengan ini, saya percaya bahwa pengecualian harus tetap, well, pengecualian, dan "kasus ideal" harus berjalan tanpa memukul satu pun.
Kita dapat menggunakan pengecualian builtin Django yang melekat pada model bernama .DoesNotExist
. Jadi, kita tidak perlu mengimpor ObjectDoesNotExist
pengecualian.
Alih-alih melakukan:
from django.core.exceptions import ObjectDoesNotExist
try:
content = Content.objects.get(name="baby")
except ObjectDoesNotExist:
content = None
Kita bisa melakukan ini:
try:
content = Content.objects.get(name="baby")
except Content.DoesNotExist:
content = None
Ini adalah peniru dari get_object_or_404 Django kecuali bahwa metode mengembalikan Tidak ada. Ini sangat berguna ketika kita harus menggunakan only()
kueri untuk hanya mengambil bidang tertentu. Metode ini dapat menerima model atau queryset.
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
Mungkin lebih baik Anda gunakan:
User.objects.filter(username=admin_username).exists()