How the web works: HTML, CSS, requests, and forms
A web application turns a request into a response. We will build a project tracker: a signed-in person creates projects, records tasks, and searches only their own work. Start with the page a browser can display.
Trace a browser request and write a labeled HTML form without assuming the browser owns application data.
Before you start
You need basic Python functions and collections. Classes are introduced with Django models; no previous web development is required.
Explanation
A URL identifies a resource. For a normal page visit, the browser sends an HTTP GET request; the server returns a status, headers, and a body. HTML describes headings, links, labels, and controls. CSS changes presentation. Django will later create the HTML on the server. This course uses templates and small forms rather than requiring a JavaScript framework.
A form groups controls with names. On submission, the browser sends those name/value pairs, not the labels a person sees. The label's for value must match the input's id. A GET form is appropriate for search: its query can be bookmarked. A POST form is appropriate for a change, such as adding a task; Django will require a CSRF token. Neither the input's required attribute nor its maxlength replaces server validation.
Save a small HTML file locally and open it in your browser. A local file can display the form, but a server is needed to process it. Our finished app will use a separate project owner stored in the database. The browser will never be allowed to choose that owner.
Worked example
This example is a fragment to place in the named project file; it is not a standalone program.
<h1>Find a task</h1>
<form method="get" action="/projects/1/">
<label for="q">Search task titles</label>
<input id="q" name="q" maxlength="100">
<button type="submit">Search</button>
</form>
Expected behavior
Typing release and submitting sends a GET request to /projects/1/?q=release. This HTML fragment illustrates the request shape; that project URL will not exist until later lessons.
Common mistakes
A placeholder is not a label. GET requests must not delete or create records. Text entered into a form is untrusted even when the person is signed in.
Guided practice
Change the button text, then inspect the input in browser developer tools. Explain why changing its name to search would require changing the server code that reads q.
Independent practice
Write a second labeled select control named status, with todo and done options. Predict the resulting query string. Success means keyboard users can reach each control and the browser sends both named values.
Check your work
Keep a small record of your prediction, observed result, and one failing case. The task runs locally; StringClass's Mark complete button records self-study progress and does not execute or grade the project. Use the tests introduced later to protect behavior as the application grows.
Recap
Trace a browser request and write a labeled HTML form without assuming the browser owns application data.
References
Official documentation. Course examples target Django 5.2 LTS, Python 3.12–3.14. Editorial verification: October 26, 2026.