Відповіді:
Не існує "побудованого" способу для цього. Джанго щоразу підніме виняток DoesNotExist. Ідіоматичний спосіб впоратися з цим у python - це загортати його у спробу лову:
try:
go = SomeModel.objects.get(foo='bar')
except SomeModel.DoesNotExist:
go = None
Що я зробив, це підкласи моделей. Менеджер, створити safe_get
подібний код вище і використовувати цей менеджер для моїх моделей. Таким чином , ви можете написати: SomeModel.objects.safe_get(foo='bar')
.
SomeModel.objects.filter(foo='bar').first()
це повертає перший матч, або None. Він не провалюється, якщо є кілька випадків типуqueryset.get()
filter().first()
я думаю, що виняток - це шлях.
Оскільки django 1.6, ви можете використовувати метод first (), наприклад:
Content.objects.filter(name="baby").first()
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")
go буде "None", якщо жоден запис, який не відповідає, ще не поверне вміст.
Примітка. Він збільшує виняток MultipleObjectsReturned, якщо більше одного запису повертається для name = "baby"
Ви можете це зробити так:
go = Content.objects.filter(name="baby").first()
Тепер змінна go може бути або об'єктом, який ви хочете, або None
Посилання: https://docs.djangoproject.com/en/1.8/ref/models/querysets/#django.db.models.query.QuerySet.first
Щоб полегшити ситуацію, ось фрагмент коду, який я написав, на основі вхідних даних із чудових відповідей тут:
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 ()
ви можете використовувати exists
з фільтром:
Content.objects.filter(name="baby").exists()
#returns False or True depending on if there is anything in the QS
просто альтернатива, якщо ви хочете знати, чи вона існує
Note: If you only want to determine if at least one result exists (and don’t need the actual objects), it’s more efficient to use exists().
exists()
він буде використаний з if
пунктом перед тим, як отримати об'єкт, отже, спричинивши подвійне потрапляння на db. Я все одно буду тримати коментар навколо, якщо він допомагає комусь іншому.
Поводження з винятками в різних точках ваших поглядів може бути справді громіздким .. Щодо визначення користувальницького менеджера моделей у файлі models.py, наприклад
class ContentManager(model.Manager):
def get_nicely(self, **kwargs):
try:
return self.get(kwargs)
except(KeyError, Content.DoesNotExist):
return None
а потім включити його до змістового класу Model
class Content(model.Model):
...
objects = ContentManager()
Таким чином, це може бути легко вирішено у поглядах, тобто
post = Content.objects.get_nicely(pk = 1)
if post:
# Do something
else:
# This post doesn't exist
return self.get(**kwargs)
він працював на мене. Не кажучи, що у відповіді нічого поганого, лише порада для тих, хто намагається використовувати його з пізнішими версіями (або з будь-яким іншим, що перешкоджало мені працювати).
Це одна з таких дратівливих функцій, яку ви, можливо, не хочете повторно реалізовувати:
from annoying.functions import get_object_or_None
#...
user = get_object_or_None(Content, name="baby")
get_object_or_None
але виявив, що він все ще піднімається, MultipleObjectsReturned
якщо більше одного об'єкта. Таким чином, користувач може розглянути питання про оточення з try-except
(що ця функція вже є try-except
).
Я думаю, що це не погана ідея 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.")
Більше про get_object_or_404 () можна прочитати в онлайн-документації django.
З 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()
Ось варіант щодо функції помічника, що дозволяє необов'язково передавати QuerySet
екземпляр, якщо ви хочете отримати унікальний об'єкт (за наявності) з набору запитів, відмінного all
від набору об'єктів моделі (наприклад, із підмножини дочірніх елементів, що належать до батьківський екземпляр):
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)
як попередньо обговорювалосяobj = get_unique_or_none(Model, parent.children, **kwargs)
Без винятку:
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 вбудований у моделі, названі як .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
Це копія коду з get_object_or_404 Django, за винятком того, що метод повертає None. Це надзвичайно корисно, коли нам потрібно використовувати only()
запит лише для отримання певних полів. Цей метод може приймати модель або набір запитів.
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
Можливо, краще використовувати:
User.objects.filter(username=admin_username).exists()