Respuestas:
No hay una forma "integrada" de hacer esto. Django generará la excepción DoesNotExist cada vez. La forma idiomática de manejar esto en python es envolverlo en un intento de captura:
try:
go = SomeModel.objects.get(foo='bar')
except SomeModel.DoesNotExist:
go = None
Lo que sí hice fue crear subclases de modelos. Administrador, crear un safe_get
código similar al anterior y usar ese administrador para mis modelos. De esa manera se puede escribir: SomeModel.objects.safe_get(foo='bar')
.
SomeModel.objects.filter(foo='bar').first()
esto devuelve la primera coincidencia, o Ninguno. No falla si hay varias instancias comoqueryset.get()
filter().first()
, creo que la excepción es el camino a seguir.
Desde django 1.6 puede usar el método first () de esta manera:
Content.objects.filter(name="baby").first()
get()
genera unaDoesNotExist
excepción si no se encuentra un objeto para los parámetros dados. Esta excepción también es un atributo de la clase de modelo. LaDoesNotExist
excepción hereda dedjango.core.exceptions.ObjectDoesNotExist
Puede atrapar la excepción y asignar None
para ir.
from django.core.exceptions import ObjectDoesNotExist
try:
go = Content.objects.get(name="baby")
except ObjectDoesNotExist:
go = None
Puede crear una función genérica para esto.
def get_or_none(classmodel, **kwargs):
try:
return classmodel.objects.get(**kwargs)
except classmodel.DoesNotExist:
return None
Use esto como a continuación:
go = get_or_none(Content,name="baby")
go será None si ninguna entrada coincide con otra, devolverá la entrada de Contenido.
Nota: Se generará una excepción MultipleObjectsReturned si se devuelve más de una entrada para name = "baby"
Puedes hacerlo de esta manera:
go = Content.objects.filter(name="baby").first()
Ahora ir variable podría ser el objeto que desea o Ninguno
Ref: https://docs.djangoproject.com/en/1.8/ref/models/querysets/#django.db.models.query.QuerySet.first
Para facilitar las cosas, aquí hay un fragmento del código que escribí, basado en las entradas de las maravillosas respuestas aquí:
class MyManager(models.Manager):
def get_or_none(self, **kwargs):
try:
return self.get(**kwargs)
except ObjectDoesNotExist:
return None
Y luego en tu modelo:
class MyModel(models.Model):
objects = MyManager()
Eso es. Ahora tiene MyModel.objects.get () así como MyModel.objetcs.get_or_none ()
podrías usar exists
con un filtro:
Content.objects.filter(name="baby").exists()
#returns False or True depending on if there is anything in the QS
solo una alternativa para si solo quieres saber si 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()
lo tanto , se usará con una if
cláusula antes de recuperar el objeto, por lo tanto, causará un doble golpe a la base de datos. Todavía mantendré el comentario en caso de que ayude a alguien más.
Manejar excepciones en diferentes puntos de sus vistas podría ser realmente engorroso ... ¿Qué pasa con la definición de un Model Manager personalizado, en el archivo models.py, como
class ContentManager(model.Manager):
def get_nicely(self, **kwargs):
try:
return self.get(kwargs)
except(KeyError, Content.DoesNotExist):
return None
y luego incluirlo en la clase de modelo de contenido
class Content(model.Model):
...
objects = ContentManager()
De esta manera se puede tratar fácilmente en las vistas, es decir
post = Content.objects.get_nicely(pk = 1)
if post:
# Do something
else:
# This post doesn't exist
return self.get(**kwargs)
que funcione para mí. Por no decir que hay algo mal con la respuesta, solo un consejo para cualquiera que intente usarlo con versiones posteriores (o con cualquier otra cosa que no funcionó para mí).
Es una de esas molestas funciones que quizás no quieras volver a implementar:
from annoying.functions import get_object_or_None
#...
user = get_object_or_None(Content, name="baby")
get_object_or_None
pero encontré que aún se eleva MultipleObjectsReturned
si hay más de un objeto. Por lo tanto, el usuario podría considerar rodearse con un try-except
(que la función en sí try-except
ya tiene).
Creo que no es mala idea 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 ejemplo es 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.")
Puede leer más sobre get_object_or_404 () en la documentación en línea de django.
Desde django 1.7 en adelante, puede hacer como:
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):
...
La ventaja de "MyQuerySet.as_manager ()" es que funcionará lo siguiente:
MyModel.objects.filter(...).get_or_none()
MyModel.objects.get_or_none()
Aquí hay una variación en la función auxiliar que le permite pasar opcionalmente una QuerySet
instancia, en caso de que desee obtener el objeto único (si está presente) de un conjunto de consultas que no sea el conjunto de consultas de all
objetos del modelo (por ejemplo, de un subconjunto de elementos secundarios que pertenecen a un instancia principal):
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
Esto se puede usar de dos maneras, por ejemplo:
obj = get_unique_or_none(Model, **kwargs)
como se discutió anteriormenteobj = get_unique_or_none(Model, parent.children, **kwargs)
Sin excepción:
if SomeModel.objects.filter(foo='bar').exists():
x = SomeModel.objects.get(foo='bar')
else:
x = None
Usando una excepción:
try:
x = SomeModel.objects.get(foo='bar')
except SomeModel.DoesNotExist:
x = None
Hay una pequeña discusión sobre cuándo se debe usar una excepción en python. Por un lado, "es más fácil pedir perdón que permiso". Si bien estoy de acuerdo con esto, creo que una excepción debería permanecer, bueno, la excepción, y el "caso ideal" debería ejecutarse sin golpear a uno.
Podemos usar la excepción incorporada de Django que se adjunta a los modelos nombrados como .DoesNotExist
. Por lo tanto, no tenemos que importar ObjectDoesNotExist
excepciones.
En cambio haciendo:
from django.core.exceptions import ObjectDoesNotExist
try:
content = Content.objects.get(name="baby")
except ObjectDoesNotExist:
content = None
Podemos hacer esto:
try:
content = Content.objects.get(name="baby")
except Content.DoesNotExist:
content = None
Este es un imitador de get_object_or_404 de Django, excepto que el método devuelve Ninguno. Esto es extremadamente útil cuando tenemos que usar la only()
consulta para recuperar ciertos campos solamente. Este método puede aceptar un modelo o un 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
Quizás sea mejor que uses:
User.objects.filter(username=admin_username).exists()