0–5 min
Real Hook
5–25 min
Core Concept
25–45 min
Live Coding
45–55 min
You Code It
55–60 min
Cheat Sheet
🔥 Real-World Hook (0–5 min)

Writing raw SQL for every database operation is like assembling IKEA furniture without the instructions — possible but painful.

Django's ORM translates Python into SQL automatically. Student.objects.filter(dept="CS", gpa__gt=3.5) — that is your SQL query. No string building, no injection risk, no connection management. Used by every Django company in India.

🔎 ORM = Object-Relational Mapping (5–25 min)

💡 Analogy

The ORM is a translator. You speak Python, it speaks SQL. Student.objects.all() → SELECT * FROM students. You never need to write SQL directly — but understanding what SQL it generates helps you write faster queries.

💻 Live Coding — ORM Query Toolkit (25–45 min)

from students.models import Student

# ── Basic CRUD ──────────────────────────────────────────────────────────────

# CREATE
s = Student.objects.create(name="Priya", email="p@mail.com", dept="CS", gpa=3.9)

# READ
all_students = Student.objects.all()              # SELECT *
cs_students  = Student.objects.filter(dept="CS")    # WHERE dept='CS'
one          = Student.objects.get(pk=1)          # WHERE id=1 (raises if not found)
first        = Student.objects.first()            # LIMIT 1

# UPDATE
Student.objects.filter(name="Priya").update(gpa=3.95)

# DELETE
Student.objects.filter(gpa__lt=2.0).delete()

# ── Advanced Filters ────────────────────────────────────────────────────────
# __ (double underscore) = "lookup" — maps to SQL operators
passing      = Student.objects.filter(gpa__gte=3.5)        # gpa >= 3.5
cs_pass      = Student.objects.filter(dept="CS", gpa__gt=3.5) # AND
with_a       = Student.objects.filter(name__icontains="a")    # LIKE '%a%' case-insensitive
top3         = Student.objects.order_by("-gpa")[:3]            # ORDER BY gpa DESC LIMIT 3

# ── Aggregation ──────────────────────────────────────────────────────────────
from django.db.models import Count, Avg, Max

stats = Student.objects.aggregate(
    total=Count("id"),
    avg_gpa=Avg("gpa"),
    max_gpa=Max("gpa")
)
print(stats)  # {'total': 8, 'avg_gpa': 3.5, 'max_gpa': 3.9}

# Per-department stats
dept_stats = (Student.objects
    .values("dept")
    .annotate(count=Count("id"), avg=Avg("gpa"))
    .order_by("-avg"))
for d in dept_stats:
    print(f"{d['dept']}: {d['count']} students, avg GPA {d['avg']:.2f}")
🎯 You Code It (45–55 min)
  1. Open your Django project from Day 7 in the shell: python manage.py shell
  2. Create 8 students covering CS, IT, EC, ME departments with varied GPAs
  3. Query: All CS students with GPA > 3.5, ordered by GPA descending
  4. Query: Count of students per department using values() + annotate()
  5. Query: Update all students with GPA below 2.0 to have gpa = 2.0 (floor correction)
  6. Query: Get the student with the highest GPA in each department
  7. Show: Run all queries in shell, show instructor the output

📄 Day 8 Cheat Sheet — Django ORM

QuerySet Methods

.all()All rows
.filter(**kwargs)WHERE condition
.exclude(**kwargs)WHERE NOT
.get(**kwargs)One row (raises if 0 or >1)
.first() .last()First / last row
.count()COUNT(*)

Lookup Operators

field__exact=v= v (default)
field__gt=v> v
field__gte=v>= v
field__lt=v< v
field__icontains=vLIKE %v% (case-insensitive)
field__in=[a,b,c]IN (a,b,c)

Create / Update / Delete

Model.objects.create(**data)INSERT + save
obj.save()INSERT or UPDATE
qs.update(field=val)UPDATE all in qs
obj.delete()DELETE one
qs.delete()DELETE all in qs
get_or_create(**kwargs)Find or create

Aggregation

from django.db.models import Count,AvgImport
.aggregate(total=Count("id"))Single stat
.values("dept")GROUP BY dept
.annotate(c=Count("id"))Add agg to each group
.order_by("-avg")Sort groups
.select_related("fk")JOIN in one query