Code Reference

QuerySet

Django · Reference cheat sheet

QuerySet

Django · Reference cheat sheet


📋 Overview

A QuerySet is a lazy, chainable representation of a DB query. Evaluation happens on iteration, list(), bool(), slicing with step, or terminal methods (get, count, exists, aggregate). Optimize with select_related / prefetch_related and defer unused fields.

🔧 Core concepts

APIRole
filter / excludeNarrow rows (Q for OR/complex)
getExactly one row or raise
create / get_or_create / update_or_createWrite helpers
annotate / aggregatePer-row / whole-set aggregates
order_by / distinctSort / unique
values / values_listDicts / tuples instead of models
select_relatedJOIN for FK / O2O
prefetch_relatedSeparate query for M2M / reverse FK
only / deferColumn subset
iteratorStream large results

Lookups: field__lookup (exact, iexact, contains, in, gt, isnull, …).

💡 Examples

Filtering and Q objects:

from django.db.models import Q, Count

Article.objects.filter(is_published=True).exclude(author=None)

Article.objects.filter(
    Q(title__icontains="django") | Q(tags__name="python")
).distinct()

Related + annotate:

qs = (
    Article.objects.filter(is_published=True)
    .select_related("author")
    .prefetch_related("tags")
    .annotate(tag_count=Count("tags"))
    .order_by("-published_at")
)

Updates and existence:

Article.objects.filter(pk=1).update(is_published=True)  # no signals
Article.objects.filter(slug="hello").exists()
Article.objects.values_list("id", flat=True)

⚠️ Pitfalls

  • N+1: accessing .author / .tags.all() in a loop without prefetch.
  • Evaluating the same queryset twice unexpectedly (cache after first eval).
  • get() raises DoesNotExist / MultipleObjectsReturned.
  • Chaining after slicing can be restricted; prefer filter before slice.
  • update() / bulk_create skip save() and most signals.

On this page