Django
QuerySet
Performance
Optimization
Python

Fastest way to get the first object from a queryset in django?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Getting the first row from a Django queryset is usually simple: use first(). It produces a LIMIT 1 query and returns either the object or None, which is exactly what most code wants.

The real performance question is usually not first() versus [0]. It is whether the queryset has the right filter, ordering, and database index behind it.

Use first() as the default

When you want one optional row, QuerySet.first() is the cleanest choice:

python
1from blog.models import Article
2
3latest_article = (
4    Article.objects
5    .filter(status="published")
6    .order_by("-published_at")
7    .first()
8)
9
10if latest_article is None:
11    print("No articles found")
12else:
13    print(latest_article.title)

This translates to a query that fetches only one row. If nothing matches, you get None instead of an exception.

Why ordering matters more than the method name

Without an order_by(), "first" may not mean what you think it means. Unless the model defines a default ordering, the database is free to return rows in whatever order is convenient.

python
article = Article.objects.filter(status="published").first()

That may be fine if any matching row is acceptable. If you mean "newest", "oldest", or "lowest price", say so explicitly:

python
newest = Article.objects.filter(status="published").order_by("-published_at").first()
oldest = Article.objects.filter(status="published").order_by("published_at").first()

Correct ordering makes the result meaningful. Indexes make it fast.

first() versus [0]

You can also write:

python
article = Article.objects.filter(status="published").order_by("-published_at")[0]

This also becomes a LIMIT 1 query, so the database work is similar. The key difference is behavior:

  • 'first() returns None for an empty queryset'
  • '[0] raises IndexError'

That makes first() the better default for normal application code. Use [0] only if an empty queryset is truly exceptional and you want the failure immediately.

get() solves a different problem

get() is for queries that should return exactly one row, such as a primary key lookup or unique slug.

python
article = Article.objects.get(pk=42)

It is not a faster replacement for "just give me the first match." get() performs stricter validation and raises exceptions when there are zero or multiple matches.

Performance comes from the query shape

For large tables, the critical factors are the filter, the order, and the supporting indexes. Consider a common pattern:

python
1latest = (
2    Article.objects
3    .filter(status="published")
4    .order_by("-published_at")
5    .first()
6)

If status and published_at are frequently used in that query path, database indexes matter far more than the Python method choice.

If you only need one field, ask for one field:

python
1latest_title = (
2    Article.objects
3    .filter(status="published")
4    .order_by("-published_at")
5    .values_list("title", flat=True)
6    .first()
7)

That avoids constructing a full model instance when you only need a single column.

Measure the SQL, not the syntax

If you want to tune performance, inspect the generated SQL and the database plan instead of arguing about tiny Python differences.

python
qs = Article.objects.filter(status="published").order_by("-published_at")
print(qs.query)
print(qs.explain())

Those tools tell you whether the database is scanning efficiently. Swapping first() for [0] will not fix a missing index.

Common Pitfalls

The most common mistake is calling first() without an explicit ordering when the business meaning of "first" actually matters.

Another issue is using get() for a non-unique query and then handling avoidable exceptions.

Developers also sometimes optimize the Django syntax while ignoring the database. If the query shape is poor or the index is missing, no small queryset API change will rescue performance.

Finally, if you only need one column, returning a full model instance adds unnecessary work.

Summary

  • Use first() when you want one row or None.
  • Add order_by() so the word "first" has a stable meaning.
  • Use [0] only when an empty queryset should raise an error.
  • Use get() only for queries that must return exactly one row.
  • Database indexing and query shape matter more than first() versus [0].

Course illustration
Course illustration

All Rights Reserved.