Respostas:
Não existe uma maneira 'embutida' de fazer isso. O Django sempre gera a exceção DoesNotExist. A maneira idiomática de lidar com isso em python é envolvê-lo em uma captura de tentativa:
try:
go = SomeModel.objects.get(foo='bar')
except SomeModel.DoesNotExist:
go = None
O que fiz foi subclassar models.Manager, criar um safe_get
código semelhante ao descrito acima e usar esse gerenciador para meus modelos. Dessa forma, você pode escrever: SomeModel.objects.safe_get(foo='bar')
.
SomeModel.objects.filter(foo='bar').first()
isso para retornar a primeira correspondência, ou Nenhuma. Ele não falhará se há vários casos comoqueryset.get()
filter().first()
, acho que a exceção é o caminho a percorrer.
Desde o django 1.6, você pode usar o método first () assim:
Content.objects.filter(name="baby").first()
get()
gera umaDoesNotExist
exceção se um objeto não for encontrado para os parâmetros fornecidos. Essa exceção também é um atributo da classe de modelo. ADoesNotExist
exceção herda dedjango.core.exceptions.ObjectDoesNotExist
Você pode capturar a exceção e atribuir None
à saída.
from django.core.exceptions import ObjectDoesNotExist
try:
go = Content.objects.get(name="baby")
except ObjectDoesNotExist:
go = None
Você pode criar uma função genérica para isso.
def get_or_none(classmodel, **kwargs):
try:
return classmodel.objects.get(**kwargs)
except classmodel.DoesNotExist:
return None
Use isto como abaixo:
go = get_or_none(Content,name="baby")
go será None se nenhuma entrada corresponder a outra, retornará a entrada Content.
Nota: Isso gerará a exceção MultipleObjectsReturned se mais de uma entrada for retornada para name = "baby"
Você pode fazer assim:
go = Content.objects.filter(name="baby").first()
Agora a variável go pode ser o objeto que você deseja ou Nenhum
Ref: https://docs.djangoproject.com/en/1.8/ref/models/querysets/#django.db.models.query.QuerySet.first
Para facilitar, aqui está um trecho do código que escrevi, com base nas entradas das maravilhosas respostas aqui:
class MyManager(models.Manager):
def get_or_none(self, **kwargs):
try:
return self.get(**kwargs)
except ObjectDoesNotExist:
return None
E então no seu modelo:
class MyModel(models.Model):
objects = MyManager()
É isso aí. Agora você tem MyModel.objects.get () e MyModel.objetcs.get_or_none ()
você poderia usar exists
com um filtro:
Content.objects.filter(name="baby").exists()
#returns False or True depending on if there is anything in the QS
apenas uma alternativa para se você só quer saber se existe
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()
será usado com a if
cláusula antes de buscar o objeto, causando um duplo golpe no banco de dados. Ainda manterei o comentário, caso isso ajude outra pessoa.
Lidar com exceções em diferentes pontos de suas visualizações pode ser realmente complicado. Que tal definir um Model Manager personalizado, no arquivo models.py, como
class ContentManager(model.Manager):
def get_nicely(self, **kwargs):
try:
return self.get(kwargs)
except(KeyError, Content.DoesNotExist):
return None
e depois incluí-lo na classe Model de conteúdo
class Content(model.Model):
...
objects = ContentManager()
Desta forma, pode ser facilmente tratado nas visualizações, isto é,
post = Content.objects.get_nicely(pk = 1)
if post:
# Do something
else:
# This post doesn't exist
return self.get(**kwargs)
ele funcione para mim. Para não dizer que há algo errado com a resposta, apenas uma dica para quem tenta usá-lo com versões posteriores (ou com o que mais o impediu de funcionar para mim).
É uma daquelas funções irritantes que você talvez não queira reimplementar:
from annoying.functions import get_object_or_None
#...
user = get_object_or_None(Content, name="baby")
get_object_or_None
mas descobri que ele ainda aumenta MultipleObjectsReturned
se houver mais de um objeto. Portanto, o usuário pode considerar cercar com a try-except
(que a própria função já possui try-except
).
Eu acho que não é uma má ideia usar 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)
Este exemplo é equivalente a:
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.")
Você pode ler mais sobre get_object_or_404 () na documentação online do django.
A partir do django 1.7, você pode fazer o seguinte:
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):
...
A vantagem de "MyQuerySet.as_manager ()" é que ambos os seguintes funcionarão:
MyModel.objects.filter(...).get_or_none()
MyModel.objects.get_or_none()
Aqui está uma variação da função auxiliar que permite passar opcionalmente em uma QuerySet
instância, caso você queira obter o objeto exclusivo (se presente) de um conjunto de consultas que não seja o conjunto de all
consultas de objetos do modelo (por exemplo, de um subconjunto de itens filhos pertencentes a um instância pai):
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
Isso pode ser usado de duas maneiras, por exemplo:
obj = get_unique_or_none(Model, **kwargs)
conforme discutido anteriormenteobj = get_unique_or_none(Model, parent.children, **kwargs)
Sem exceção:
if SomeModel.objects.filter(foo='bar').exists():
x = SomeModel.objects.get(foo='bar')
else:
x = None
Usando uma exceção:
try:
x = SomeModel.objects.get(foo='bar')
except SomeModel.DoesNotExist:
x = None
Há um pouco de argumento sobre quando alguém deve usar uma exceção em python. Por um lado, "é mais fácil pedir perdão do que permissão". Embora eu concorde com isso, acredito que uma exceção deve permanecer, bem, a exceção e o "caso ideal" deve ser executado sem atingir uma.
Podemos usar a exceção interna do Django, anexada aos modelos nomeados como .DoesNotExist
. Portanto, não precisamos importar ObjectDoesNotExist
exceção.
Em vez disso:
from django.core.exceptions import ObjectDoesNotExist
try:
content = Content.objects.get(name="baby")
except ObjectDoesNotExist:
content = None
Nós podemos fazer isso:
try:
content = Content.objects.get(name="baby")
except Content.DoesNotExist:
content = None
Este é um imitador de get_object_or_404 do Django, exceto que o método retorna None. Isso é extremamente útil quando precisamos usar a only()
consulta para recuperar apenas determinados campos. Este método pode aceitar um modelo ou um conjunto de consultas.
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
Talvez seja melhor você usar:
User.objects.filter(username=admin_username).exists()