tuplas tupla por operaciones listas leer ejemplo diccionarios diccionario convertir con comprensión arreglo python django performance django-models

python - tupla - ¿La forma más rápida de obtener el primer objeto de un conjunto de consulta en django?



operaciones con diccionarios python (8)

A menudo me parece que quiero obtener el primer objeto de un queryset en Django, o devolver None si no hay ninguno. Hay muchas formas de hacer esto que funcionan. Pero me pregunto cuál es el más eficiente.

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 ¿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 la mayor parte del tiempo, lo cual es una tarea muy intensiva en memoria cuando todo lo que realmente necesita es una prueba trivial.

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


Ahora, en Django 1.9, tienes el método first() para querysets.

YourModel.objects.all().first()

Esta es una mejor manera que .get() o [0] porque no arroja una excepción si el conjunto de consulta está vacío. Por lo tanto, no es necesario que compruebe el uso de exists()


Deberías usar los métodos django, como existe. Está ahí para que lo uses.

if qs.exists(): return qs[0] return None


Esto podría funcionar también:

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.


La respuesta correcta es

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

Que se puede usar en:

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

No querría convertirlo primero en una lista porque eso forzaría una llamada a la base de datos completa de todos los registros. Simplemente haz lo anterior y solo extraerá el primero. Incluso podría usar .order_by para asegurarse de obtener el primero que desea.

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


Puede ser así

obj = model.objects.filter(id=emp_id)[0]

o

obj = model.objects.latest(''id'')


Si planea obtener el primer elemento con frecuencia, 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 un modelo como este:

class MyModel(models.Model): objects = ManagerWithFirstQuery()

Y úsalo así:

first_object = MyModel.objects.filter(x=100).first()



r = list(qs[:1]) if r: return r[0] return None