¿La forma más rápida de obtener el primer objeto de un conjunto de consultas en Django?

Resuelto Leopd asked hace 13 años • 9 respuestas

A menudo me encuentro deseando obtener el primer objeto de un conjunto de consultas en Django, o devolverlo Nonesi no hay ninguno. Hay muchas formas de hacer esto y todas funcionan. Pero me pregunto cuál es el de mayor rendimiento.

qs = MyModel.objects.filter(blah = blah)
if qs.count() > 0:
    return qs[0]
else:
    return None

¿Esto da como resultado dos llamadas a la base de datos? Eso parece un desperdicio. ¿Es esto 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 única llamada a la base de datos, lo cual es bueno. Pero requiere crear un objeto de excepción la mayor parte del tiempo, lo cual requiere mucha memoria cuando todo lo que realmente necesitas es una prueba trivial.

¿Cómo puedo hacer esto con una sola llamada a la base de datos y sin agitar la memoria con objetos de excepción?

Leopd avatar Feb 26 '11 06:02 Leopd
Aceptado

Django 1.6 (lanzado en noviembre de 2013) introdujo los métodos convenientes first() que last()tragan la excepción resultante y regresan Nonesi el conjunto de consultas no devuelve ningún objeto.

cod3monk3y avatar Nov 18 '2013 14:11 cod3monk3y

Puedes utilizar el corte de matrices :

Entry.objects.all()[:1].get()

Que se puede utilizar con .filter():

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 extraerá el primero. Incluso podrías usarlo .order_by()para asegurarte de obtener el primero que deseas.

Asegúrese de agregar el .get()o, de lo contrario, obtendrá un QuerySet y no un objeto.

stormlifter avatar Mar 02 '2011 00:03 stormlifter

Ahora, en Django 1.9 tienes first() un método para conjuntos de consultas.

YourModel.objects.all().first()

Esta es una mejor manera que .get()o [0]porque no genera una excepción si el conjunto de consultas está vacío. Por lo tanto, no es necesario verificar usandoexists()

levi avatar Oct 06 '2016 01:10 levi