Odpowiedzi:
Nie ma „wbudowanego” sposobu, aby to zrobić. Django będzie zgłaszał wyjątek DoesNotExist za każdym razem. Idiomatycznym sposobem radzenia sobie z tym w pythonie jest zawinięcie go w try catch:
try:
go = SomeModel.objects.get(foo='bar')
except SomeModel.DoesNotExist:
go = None
To, co zrobiłem, to podklasowanie safe_get
modeli. Menedżer , stwórz podobny kod powyżej i użyj tego menedżera dla moich modeli. W ten sposób można napisać: SomeModel.objects.safe_get(foo='bar')
.
SomeModel.objects.filter(foo='bar').first()
tej wartości, zwracając pierwsze dopasowanie lub Brak. Nie zawiedzie, jeśli istnieje kilka takich przypadkówqueryset.get()
filter().first()
, myślę, że wyjątek jest najlepszym rozwiązaniem.
Od wersji django 1.6 możesz użyć metody first () w następujący sposób:
Content.objects.filter(name="baby").first()
get()
zgłaszaDoesNotExist
wyjątek, jeśli nie można znaleźć obiektu dla podanych parametrów. Ten wyjątek jest również atrybutem klasy modelu. WDoesNotExist
dziedziczy wyjątek oddjango.core.exceptions.ObjectDoesNotExist
Możesz złapać wyjątek i przypisać None
go.
from django.core.exceptions import ObjectDoesNotExist
try:
go = Content.objects.get(name="baby")
except ObjectDoesNotExist:
go = None
Możesz w tym celu utworzyć funkcję ogólną.
def get_or_none(classmodel, **kwargs):
try:
return classmodel.objects.get(**kwargs)
except classmodel.DoesNotExist:
return None
Użyj tego jak poniżej:
go = get_or_none(Content,name="baby")
go będzie Brak, jeśli żaden wpis pasujący inny nie zwróci wpisu Treść.
Uwaga: Zgłasza wyjątek MultipleObjectsReturned, jeśli zwrócono więcej niż jeden wpis dla name = "baby"
Możesz to zrobić w ten sposób:
go = Content.objects.filter(name="baby").first()
Teraz zmienna go może być obiektem, który chcesz lub Brak
Patrz: https://docs.djangoproject.com/en/1.8/ref/models/querysets/#django.db.models.query.QuerySet.first
Aby to ułatwić, oto fragment kodu, który napisałem, oparty na danych z cudownych odpowiedzi tutaj:
class MyManager(models.Manager):
def get_or_none(self, **kwargs):
try:
return self.get(**kwargs)
except ObjectDoesNotExist:
return None
A potem w twoim modelu:
class MyModel(models.Model):
objects = MyManager()
Otóż to. Teraz masz MyModel.objects.get () oraz MyModel.objetcs.get_or_none ()
możesz użyć exists
z filtrem:
Content.objects.filter(name="baby").exists()
#returns False or True depending on if there is anything in the QS
tylko alternatywa, jeśli chcesz tylko wiedzieć, czy istnieje
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()
Będzie więc używany z if
klauzulą przed pobraniem obiektu, powodując podwójne trafienie do bazy danych. Nadal będę trzymał komentarz na wypadek, gdyby pomógł komuś innemu.
Obsługa wyjątków w różnych punktach twoich widoków może być naprawdę kłopotliwa. Co z definiowaniem niestandardowego Menedżera modeli w pliku models.py, np.
class ContentManager(model.Manager):
def get_nicely(self, **kwargs):
try:
return self.get(kwargs)
except(KeyError, Content.DoesNotExist):
return None
a następnie uwzględnienie go w klasie Model treści
class Content(model.Model):
...
objects = ContentManager()
W ten sposób można łatwo sobie z tym poradzić w widokach, tj
post = Content.objects.get_nicely(pk = 1)
if post:
# Do something
else:
# This post doesn't exist
return self.get(**kwargs)
, aby działał dla mnie. Nie mówię, że coś jest nie tak z odpowiedzią, tylko wskazówka dla każdego, kto próbuje użyć jej w późniejszych wersjach (lub z czymkolwiek innym, co powstrzymuje mnie od pracy).
Jest to jedna z tych irytujących funkcji, których możesz nie chcieć ponownie wdrożyć:
from annoying.functions import get_object_or_None
#...
user = get_object_or_None(Content, name="baby")
get_object_or_None
ale stwierdziłem, że wciąż się podnosi, MultipleObjectsReturned
jeśli więcej niż jeden obiekt. Tak więc użytkownik może rozważyć otoczenie za pomocą try-except
(które sama funkcja try-except
już ma).
Myślę, że nie jest to zły pomysł 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)
Ten przykład jest równoważny z:
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.")
Możesz przeczytać więcej o get_object_or_404 () w dokumentacji online django.
Od wersji django 1.7 możesz wykonywać następujące czynności:
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):
...
Zaletą „MyQuerySet.as_manager ()” jest to, że oba poniższe elementy będą działać:
MyModel.objects.filter(...).get_or_none()
MyModel.objects.get_or_none()
Oto odmiana funkcji pomocnika, która pozwala opcjonalnie przekazać w QuerySet
instancji, na wypadek, gdybyś chciał uzyskać unikalny obiekt (jeśli jest obecny) z zestawu zapytań innego niż all
zestaw zapytań obiektów modelu (np. Z podzbioru elementów potomnych należących do instancja nadrzędna):
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
Można tego użyć na dwa sposoby, np .:
obj = get_unique_or_none(Model, **kwargs)
jak wcześniej omówionoobj = get_unique_or_none(Model, parent.children, **kwargs)
Bez wyjątku:
if SomeModel.objects.filter(foo='bar').exists():
x = SomeModel.objects.get(foo='bar')
else:
x = None
Korzystanie z wyjątku:
try:
x = SomeModel.objects.get(foo='bar')
except SomeModel.DoesNotExist:
x = None
Jest trochę kłótni na temat tego, kiedy należy użyć wyjątku w Pythonie. Z jednej strony „łatwiej prosić o wybaczenie niż o pozwolenie”. Chociaż zgadzam się z tym, uważam, że wyjątek powinien pozostać, no cóż, wyjątek, a „idealna sprawa” powinna przebiegać bez trafienia w jeden.
Możemy użyć wyjątku wbudowanego Django, który jest dołączony do modeli o nazwie as .DoesNotExist
. Więc nie musimy importować ObjectDoesNotExist
wyjątku.
Zamiast tego:
from django.core.exceptions import ObjectDoesNotExist
try:
content = Content.objects.get(name="baby")
except ObjectDoesNotExist:
content = None
Możemy to zrobić:
try:
content = Content.objects.get(name="baby")
except Content.DoesNotExist:
content = None
Jest to kopia naśladująca metodę get_object_or_404 Django, z wyjątkiem tego, że metoda zwraca None. Jest to niezwykle przydatne, gdy musimy użyć only()
zapytania, aby pobrać tylko niektóre pola. Ta metoda może zaakceptować model lub zestaw zapytań.
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
Może lepiej użyć:
User.objects.filter(username=admin_username).exists()