Migrations & ORM Queries0%

Migrations & ORM Queries

Beginner12 min read•Updated: Jul 11, 2026
Study MaterialsCheatsheet

Migrations & ORM Queries

Django's Object-Relational Mapper (ORM) translates high-level Python method calls into optimized SQL queries. The ORM's QuerySet API is lazy: queries are not executed against the database until the data is explicitly evaluated. Mastering QuerySet filtering, chaining, aggregations, and migration workflows ensures both developer productivity and database performance.


1. The QuerySet Execution Lifecycle

A QuerySet represents a collection of database rows. Creating a QuerySet does not touch the database:

Python
# No SQL is executed here! (Lazy evaluation)
published_articles = Article.objects.filter(status="published").order_by("-created_at")
 
# Database query executes ONLY when QuerySet is evaluated:
for article in published_articles: # 1. Iteration
print(article.title)
 
article_list = list(published_articles) # 2. Converting to list
count = published_articles.count() # 3. Aggregation (executes SELECT COUNT(*))
first = published_articles.first() # 4. Slicing / Indexing (LIMIT 1)
exists = published_articles.exists() # 5. Boolean check (EXISTS query)

2. QuerySet Filtering with Field Lookups

Django uses double-underscore (__) notation for SQL operators:

Python
# Exact match
Article.objects.filter(status__exact="published")
 
# Case-insensitive contains (SQL LIKE '%django%')
Article.objects.filter(title__icontains="django")
 
# Greater than or equal (SQL >=)
Article.objects.filter(view_count__gte=1000)
 
# SQL IN operator
Article.objects.filter(category__slug__in=["python", "django", "backend"])
 
# Date filters
Article.objects.filter(created_at__year=2026)
 
# Spanning relationships across foreign keys:
# Find all articles written by user with username 'dr_sumit'
Article.objects.filter(author__username="dr_sumit")

3. Complex Queries with Q Objects and F Expressions

Logical OR Queries with Q

Standard .filter(a=1, b=2) combines clauses with SQL AND. To write SQL OR queries, use Q objects:

Python
from django.db.models import Q
 
# SQL: WHERE status = 'published' OR is_featured = true
query = Article.objects.filter(Q(status="published") | Q(is_featured=True))
 
# SQL: WHERE status = 'published' AND NOT author_id = 5
query = Article.objects.filter(Q(status="published") & ~Q(author__id=5))

Database Field Operations with F Expressions

F expressions reference database column values directly in SQL without loading them into Python memory:

Python
from django.db.models import F
 
# Atomically increment view_count in database (race-condition free!)
Article.objects.filter(id=1).update(view_count=F("view_count") + 1)

4. Advanced Migration Commands

Bash / Terminal
# Display status of all applied/unapplied migrations
python manage.py showmigrations
 
# Rollback an app to a specific previous migration
python manage.py migrate articles 0002
 
# Rollback an app completely
python manage.py migrate articles zero

Interactive Quiz

Practice Quiz

Question 1
What does it mean that Django QuerySets are "lazy"?
Question 2
How do you construct an SQL OR condition in Django ORM?
Question 3
Why is using F('view_count') + 1 superior to article.view_count += 1 followed by save()?
Question 4
Which method checks if matching records exist with maximum efficiency?
Question 5
What command lists all migrations across all apps along with an [X] indicating whether they have been applied?
Next Lesson

Django Admin Site

Continue learning with hands-on practice, examples, and exercises in the upcoming topic.

Related Lessons

Practice Quiz

Test your understanding of this lesson with 5 questions. Each question has one correct answer.

PrevNext