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_getmodeli. 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łaszaDoesNotExistwyjątek, jeśli nie można znaleźć obiektu dla podanych parametrów. Ten wyjątek jest również atrybutem klasy modelu. WDoesNotExistdziedziczy wyjątek oddjango.core.exceptions.ObjectDoesNotExist
Możesz złapać wyjątek i przypisać Nonego.
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ć existsz 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 ifklauzulą 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_Noneale stwierdziłem, że wciąż się podnosi, MultipleObjectsReturnedjeś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-exceptjuż 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 QuerySetinstancji, na wypadek, gdybyś chciał uzyskać unikalny obiekt (jeśli jest obecny) z zestawu zapytań innego niż allzestaw 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ć ObjectDoesNotExistwyją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()