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)

Your DRF API returns JSON. But no one wants to use curl. Users want buttons, tables, forms.

Today you build an HTML + JavaScript frontend that calls your Django API and shows real data. This is exactly how Swiggy's web frontend talks to their Python backend — fetch() hits an API endpoint, the response renders in the browser. No page reloads. Full-stack.

🌐 Browser ↔ API in 3 Steps (5–25 min)

💡 The Pattern

Step 1: User loads the HTML page — just static HTML, no data yet.
Step 2: JavaScript runs fetch("/api/students/") — calls your Django API.
Step 3: API returns JSON — JavaScript puts it in the page without reloading.

💻 Live Coding — Student Dashboard (25–45 min)

<!-- index.html -->
<!DOCTYPE html>
<html>
<head>
  <title>Student Dashboard</title>
  <style>
    body  { font-family: sans-serif; max-width: 800px; margin: 2rem auto; padding: 0 1rem; }
    table { width: 100%; border-collapse: collapse; margin-top: 1rem; }
    th, td { padding: .6rem 1rem; border: 1px solid #ddd; text-align: left; }
    th    { background: #2563eb; color: white; }
    tr:nth-child(even) { background: #f8f9fa; }
    .btn  { background:#2563eb; color:#fff; border:none; padding:.5rem 1rem; border-radius:6px; cursor:pointer; }
    .form-row { display:flex; gap:.5rem; margin:.5rem 0; }
    .form-row input { flex:1; padding:.4rem; border:1px solid #ccc; border-radius:4px; }
  </style>
</head>
<body>
  <h1>🐍 Student Dashboard</h1>

  <div class="form-row">
    <input id="name"  placeholder="Name">
    <input id="email" placeholder="Email">
    <input id="dept"  placeholder="Dept">
    <input id="gpa"   placeholder="GPA" type="number" step=".1">
    <button class="btn" onclick="addStudent()">Add</button>
  </div>

  <table>
    <thead><tr><th>Name</th><th>Email</th><th>Dept</th><th>GPA</th><th>Action</th></tr></thead>
    <tbody id="table-body"></tbody>
  </table>

  <script>
    const API = "http://127.0.0.1:8000/api/students/";

    async function loadStudents() {
      const res  = await fetch(API);
      const data = await res.json();
      const tbody = document.getElementById("table-body");
      tbody.innerHTML = data.map(s => `
        <tr>
          <td>${s.name}</td>
          <td>${s.email}</td>
          <td>${s.dept}</td>
          <td>${s.gpa}</td>
          <td><button class="btn" onclick="deleteStudent(${s.id})">Delete</button></td>
        </tr>`).join("");
    }

    async function addStudent() {
      const body = {
        name:  document.getElementById("name").value,
        email: document.getElementById("email").value,
        dept:  document.getElementById("dept").value,
        gpa:   document.getElementById("gpa").value,
      };
      await fetch(API, {
        method:  "POST",
        headers: { "Content-Type": "application/json" },
        body:    JSON.stringify(body)
      });
      loadStudents();  // refresh table
    }

    async function deleteStudent(id) {
      await fetch(`${API}${id}/`, { method: "DELETE" });
      loadStudents();
    }

    loadStudents();  // load on page open
  </script>
</body>
</html>
🎯 You Code It (45–55 min)
  1. Create the HTML file above, open it in browser — is the table loading from your API?
  2. Add an "Edit" button that shows a prompt, takes a new GPA, and sends PATCH request
  3. Add a search input + filter button: on click, fetch ?search=term and refresh table
  4. Add CSS: highlight rows where GPA < 2.5 in red background
  5. Bonus: Add department filter dropdown — selecting "CS" fetches only CS students
  6. Show: Add a student, delete one, search by name — all without page reload

📄 Day 10 Cheat Sheet — JS + Fetch API

fetch() Patterns

fetch(url)GET request
await fetch(url)Wait for response
await res.json()Parse JSON body
res.status === 200Check success
res.okTrue if 2xx status

POST / PUT / DELETE

method: "POST"Create
method: "PUT"Full update
method: "PATCH"Partial update
method: "DELETE"Delete
headers: {Content-Type: application/json}Tell server it's JSON

DOM Manipulation

document.getElementById("id")Get element
el.innerHTML = htmlSet HTML content
el.valueInput value
data.map(x => `html`).join("")Array to HTML
onclick="fn(id)"Click handler

async / await

async function fn() {}Declare async
await promiseWait for result
try { } catch(e) { }Handle errors
Promise.all([p1, p2])Run in parallel