La forma más rápida de obtener el primer objeto de un queryset en django?
A menudo me encuentro queriendo obtener el primer objeto de un queryset en Django, o devolver None
si no hay ninguno. Hay un montón de maneras de hacer esto que todos funcionan. Pero me pregunto cuál es la más performante.
qs = MyModel.objects.filter(blah = blah)
if qs.count() > 0:
return qs[0]
else:
return None
¿Esto resulta en dos llamadas a la base de datos? Eso parece un desperdicio. ¿Esto es más rápido?
qs = MyModel.objects.filter(blah = blah)
if len(qs) > 0:
return qs[0]
else:
return None
Otra opción sería:
qs = MyModel.objects.filter(blah = blah)
try:
return qs[0]
except IndexError:
return None
Esto genera una sola llamada a la base de datos, lo cual es bueno. Pero requiere crear un objeto de excepción muchos de los tiempo, que es una cosa que consume mucha memoria cuando todo lo que realmente necesitas es una trivial prueba if.
¿Cómo puedo hacer esto con una sola llamada a la base de datos y sin agitar la memoria con objetos de excepción?
8 answers
Django 1.6 (publicado en noviembre de 2013) introdujo los métodos de conveniencia first()
y last()
que tragan la excepción resultante y devuelven None
si el queryset no devuelve ningún objeto.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-11-18 14:07:42
La respuesta correcta es
Entry.objects.all()[:1].get()
Que se puede utilizar en:
Entry.objects.filter()[:1].get()
No querrás convertirlo primero en una lista porque eso forzaría una llamada completa a la base de datos de todos los registros. Simplemente haga lo anterior y solo tirará de la primera. Incluso podría usar .order_by
para asegurarse de obtener el primero que desee.
Asegúrese de agregar el .get()
o de lo contrario obtendrá un QuerySet y no un objeto.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-07-31 22:35:19
r = list(qs[:1])
if r:
return r[0]
return None
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-02-25 23:30:36
Ahora, en Django 1.9 tienes first()
método para querysets.
YourModel.objects.all().first()
Esta es una mejor manera que .get()
o [0]
porque no arroja una excepción si queryset está vacío, por lo tanto, no necesita verificar usando exists()
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-06 02:01:57
Si planea obtener el primer elemento a menudo, puede extender QuerySet en esta dirección:
class FirstQuerySet(models.query.QuerySet):
def first(self):
return self[0]
class ManagerWithFirstQuery(models.Manager):
def get_query_set(self):
return FirstQuerySet(self.model)
Defina el modelo así:
class MyModel(models.Model):
objects = ManagerWithFirstQuery()
Y úsalo así:
first_object = MyModel.objects.filter(x=100).first()
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-03-13 12:24:01
Puede ser así
obj = model.objects.filter(id=emp_id)[0]
O
obj = model.objects.latest('id')
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-06-25 21:07:41
Debe usar métodos django, como exists. Está ahí para que lo uses.
if qs.exists():
return qs[0]
return None
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-09-13 22:23:33
Esto también podría funcionar:
def get_first_element(MyModel):
my_query = MyModel.objects.all()
return my_query[:1]
Si está vacío, devuelve una lista vacía, de lo contrario devuelve el primer elemento dentro de una lista.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-05 14:06:32