Самый быстрый способ получить первый объект из queryset в django?
часто я обнаруживаю, что хочу получить первый объект из queryset в Django или вернуть None если нет. Есть много способов сделать это, которые все работают. Но мне интересно, что является наиболее эффективным.
qs = MyModel.objects.filter(blah = blah)
if qs.count() > 0:
return qs[0]
else:
return None
это приводит к двум вызовам базы данных? Это кажется расточительным. Это быстрее?
qs = MyModel.objects.filter(blah = blah)
if len(qs) > 0:
return qs[0]
else:
return None
другой вариант:
qs = MyModel.objects.filter(blah = blah)
try:
return qs[0]
except IndexError:
return None
это создает один вызов базы данных, что хорошо. Но требует создания объект исключения много времени, что очень интенсивно требует памяти, когда все, что вам действительно нужно,-это тривиальный if-тест.
как я могу сделать это только с одним вызовом базы данных и без сбивания памяти с объектами исключения?
8 ответов:
Django 1.6 (выпущен в ноябре 2013 года) представил методы
first()иlast()которые проглатывают полученное исключение и возвращаютNoneесли запрос не возвращает никаких объектов.
правильный ответ
Entry.objects.all()[:1].get()что можно использовать в:
Entry.objects.filter()[:1].get()вы не хотели бы сначала превратить его в список, потому что это заставит полный вызов базы данных всех записей. Просто сделайте выше, и он будет тянуть только первый. Вы даже можете использовать
.order_byчтобы убедиться, что вы получите первое, что вы хотите.обязательно добавьте
.get()иначе вы получите объект QuerySet, а не объект.
теперь, в Django 1.9 у вас есть
first()метод для запросов.YourModel.objects.all().first()это лучше, чем
.get()или[0]потому что он не выдает исключение, если queryset пуст, поэтому вам не нужно проверять с помощьюexists()
Если вы планируете часто получать первый элемент-вы можете расширить QuerySet в этом направлении:
class FirstQuerySet(models.query.QuerySet): def first(self): return self[0] class ManagerWithFirstQuery(models.Manager): def get_query_set(self): return FirstQuerySet(self.model)определить модель следующим образом:
class MyModel(models.Model): objects = ManagerWithFirstQuery()и использовать его так:
first_object = MyModel.objects.filter(x=100).first()
вы должны использовать методы django, как существует. Его там для вас, чтобы использовать его.
if qs.exists(): return qs[0] return None
Это может работать также:
def get_first_element(MyModel): my_query = MyModel.objects.all() return my_query[:1]если он пуст, то возвращает пустой список, в противном случае он возвращает первый элемент внутри списка.
Comments