Unit 1: Introduction to Django

INT253 — Web Development In Python Using Django 9 min read

I. Orientation: The Framework and Its Governing Ideas

Django is a high-level, open-source web framework written in Python, created in 2003 at the Lawrence Journal-World newspaper in Lawrence, Kansas by Adrian Holovaty and Simon Willison, and released publicly under the BSD licence in July 2005. It is named after the guitarist Django Reinhardt and is maintained by the Django Software Foundation (founded 2008). Because it grew inside a newsroom, its design assumes rapid, deadline-driven development of database-backed, content-heavy sites — the slogan is "The web framework for perfectionists with deadlines."

Defining properties that the rest of the unit depends on:

  • Batteries-included: ORM, template engine, form handling, authentication, session management, an automatic admin site and a development server all ship in the box — no assembling of separate libraries.
  • MVT architecture: Django's variant of MVC — Model (data layer, models.py), View (business logic, views.py), Template (presentation, .html files). The "controller" role is played by the framework itself via URL dispatching (urls.py).
  • DRY (Don't Repeat Yourself): a fact lives in one place — e.g. a model field defined once generates the database column, the form widget and the admin control.
  • Loose coupling / pluggability: the unit of reuse is the app, a self-contained Python package that can be dropped into any project by listing it in INSTALLED_APPS.
  • Explicit configuration: unlike convention-driven frameworks, Django requires settings to be declared in settings.py (DEBUG, DATABASES, ALLOWED_HOSTS).
  • Convention of the request cycle: URL → urls.py resolver → view function → model/template → HttpResponse.

II. Introduction to Django

Positioning the framework among Python web tools

A. What Django Is and Why It Exists

  • Definition: a server-side (back-end) framework that maps HTTP requests to Python callables and returns HTTP responses, with an ORM abstracting SQL.
  • Full-stack vs micro-framework: Flask supplies routing and templating only; Django supplies ORM, migrations, admin and auth as well. Choose Flask for a 100-line API, Django for a site with users, permissions and a schema.
  • Security defaults: CSRF tokens required on POST forms, SQL injection prevented by parameterised ORM queries, XSS prevented by auto-escaping in templates, passwords stored with PBKDF2 by default.
  • Scale evidence: Instagram, Pinterest, Mozilla and Disqus are built on Django, demonstrating it is not limited to small sites.
  • Versioning: feature releases roughly every 8 months; LTS releases (e.g. 3.2, 4.2) receive ~3 years of security support — production projects normally pin to an LTS.

III. Installing Python and Django

Environment setup and dependency isolation

A. Installing Python

  • Version requirement: Django 4.2 requires Python 3.8+; always verify with python --version (Windows) or python3 --version (macOS/Linux).
  • Windows installer caveat: tick "Add Python to PATH" during installation, otherwise python and pip are unresolved in the terminal.
  • pip: the package installer, bundled since Python 3.4; check with pip --version.

B. Installing Django

Django is never installed globally for real work — it is installed inside a virtual environment, an isolated directory holding its own site-packages, so Project A can use Django 3.2 while Project B uses 4.2.

BASH
python -m venv myenv                 # create the environment
myenv\Scripts\activate               # activate (Windows)
source myenv/bin/activate            # activate (macOS / Linux)
pip install django                   # latest version
pip install django==4.2.11           # a pinned version
python -m django --version           # verify
pip freeze > requirements.txt        # record dependencies
  • deactivate: returns to the system interpreter; the shell prompt prefix (myenv) indicates the environment is active.
  • requirements.txt: reinstalled elsewhere with pip install -r requirements.txt, guaranteeing reproducible builds.

IV. Setting up Project in Editor

Making the IDE aware of the interpreter

A. Editor Configuration

  • VS Code: open the project folder, then Ctrl+Shift+P → "Python: Select Interpreter" and choose ./myenv/Scripts/python.exe; without this, imports such as from django.db import models are flagged as unresolved.
  • Useful extensions: Python (Microsoft), Pylance for IntelliSense, and a Django template extension so {% %} and {{ }} tags are highlighted in .html files.
  • PyCharm Professional: offers a Django project type that sets DJANGO_SETTINGS_MODULE and runs manage.py tasks from a dedicated console.
  • Integrated terminal: run all manage.py commands from the directory containing manage.py, with the venv active.
  • .gitignore essentials: exclude myenv/, __pycache__/, *.pyc, db.sqlite3 and any .env file holding SECRET_KEY.

V. Projects and Apps Overview

The two-level unit of organisation

A. The Distinction

  • Project: the whole website — a container holding configuration (settings, root URLconf, WSGI/ASGI entry point). One project per site.
  • App: a component doing one job — a blog, a poll, an authentication module. A project contains many apps; one app may be reused in many projects.
  • Django's own analogy: an app is a "web application that does something"; the project is "a collection of configuration and apps for a particular website."
  • Registration: an app is inert until its name is added to INSTALLED_APPS in settings.py; only then are its models discovered by migrations and its templates found by the loader.
  • Built-in apps already listed: django.contrib.admin, .auth, .contenttypes, .sessions, .messages, .staticfiles.
  • Design rule of thumb: if a feature could be published to PyPI independently (e.g. a comments system), it deserves its own app.

VI. Creating Your First Project

Command, output and first run

A. The startproject Command

BASH
django-admin startproject mysite      # creates outer mysite/ + inner mysite/
cd mysite
python manage.py runserver            # http://127.0.0.1:8000/
  • The trailing dot: django-admin startproject mysite . creates the config package in the current directory, avoiding the duplicated mysite/mysite/ nesting.
  • First run output: the "rocket ship" success page appears only while DEBUG = True.
  • Unapplied-migrations warning: runserver warns of 18 unapplied migrations from the built-in apps; python manage.py migrate creates db.sqlite3 with tables such as auth_user and django_session.
  • Custom port/host: python manage.py runserver 8080 or runserver 0.0.0.0:8000 to expose on a LAN. The development server auto-reloads on file save and must never be used in production.

VII. Project Structure

What each generated file does

A. File-by-File Anatomy

TEXT
mysite/                 # outer container (name is arbitrary)
├── manage.py           # command-line utility
└── mysite/             # configuration package
    ├── __init__.py     # marks the directory as a Python package
    ├── settings.py     # all configuration
    ├── urls.py         # root URLconf ("table of contents")
    ├── asgi.py         # ASGI entry point (async servers)
    └── wsgi.py         # WSGI entry point (Gunicorn, mod_wsgi)
  • settings.py key variables:
    • BASE_DIR: Path(__file__).resolve().parent.parent — the project root, used to build paths.
    • SECRET_KEY: cryptographic signing of sessions and CSRF tokens; must be kept out of version control.
    • DEBUG: True gives full tracebacks; must be False in production, which then requires ALLOWED_HOSTS to list valid domains.
    • INSTALLED_APPS, MIDDLEWARE (ordered request/response hooks), TEMPLATES, DATABASES (SQLite by default), STATIC_URL = 'static/'.
  • urls.py: contains urlpatterns = [path('admin/', admin.site.urls)]; app URLs are attached with include().
  • db.sqlite3: appears only after the first migrate.

VIII. django-admin & manage.py Commands

The two command-line entry points

A. The Two Utilities Contrasted

  1. django-admin: installed on PATH by pip, project-independent; used before a project exists — chiefly startproject. It has no knowledge of DJANGO_SETTINGS_MODULE unless it is set manually.
  2. manage.py: auto-generated per project; a thin wrapper that sets os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings') and then calls execute_from_command_line. Use it for everything after the project is created, because it knows the project's settings and database.

B. Command Reference

Command Effect
startproject <name> Scaffold a new project
startapp <name> Scaffold a new app
runserver [port] Start the auto-reloading dev server
makemigrations Turn model changes into migration files
migrate Apply migrations to the database
createsuperuser Create an admin account
shell Python REPL with Django loaded
dbshell Open the database's own client
test Run the test suite
collectstatic Gather static files for deployment
showmigrations List migrations and their applied state
  • Discovery: python manage.py help lists all commands grouped by the app supplying them; apps can add their own via a management/commands/ directory.

IX. App Structures

Files generated inside an app

A. Anatomy of an App Package

TEXT
blog/
├── __init__.py
├── admin.py        # register models with the admin site
├── apps.py         # BlogConfig class; app metadata
├── migrations/     # schema history, starts with __init__.py only
│   └── __init__.py
├── models.py       # database tables as Python classes
├── tests.py        # test cases
└── views.py        # request-handling functions/classes
  • models.py: each class subclasses django.db.models.Model; each attribute (CharField, IntegerField) becomes a column.
  • views.py: a view receives an HttpRequest and returns an HttpResponsedef index(request): return HttpResponse("Hello").
  • apps.py: holds class BlogConfig(AppConfig) with default_auto_field and name = 'blog'; referenced by INSTALLED_APPS.
  • Files not generated but conventionally added: urls.py (app-level URLconf), forms.py, templates/blog/, static/blog/ — the app-name subdirectory prevents template name collisions between apps.

X. Creating an App

From scaffold to first response

A. The Full Sequence

BASH
python manage.py startapp blog
  1. Register it in settings.py:
    PYTHON
       INSTALLED_APPS = [ ..., 'blog', ]   # or 'blog.apps.BlogConfig'
  2. Write a view in blog/views.py:
    PYTHON
       from django.http import HttpResponse
       def index(request):
           return HttpResponse("Welcome to the blog.")
  3. Create blog/urls.py:
    PYTHON
       from django.urls import path
       from . import views
       app_name = 'blog'
       urlpatterns = [path('', views.index, name='index')]
  4. Include it in mysite/urls.py:
    PYTHON
       from django.urls import path, include
       urlpatterns = [
           path('admin/', admin.site.urls),
           path('blog/', include('blog.urls')),
       ]
  5. Run python manage.py runserver and visit http://127.0.0.1:8000/blog/.

B. Applications and Limitations

  • Application: the same app, unmodified, can be pip-packaged and reused across projects — the practical payoff of loose coupling.
  • Naming constraints: an app name must be a valid Python identifier and must not clash with an installed module (test, django, json).
  • Limitation: startapp does not create urls.py, forms.py or template folders — these must be added by hand.
  • Limitation: adding an app to INSTALLED_APPS after writing models still requires makemigrations blog followed by migrate; otherwise the tables never exist and queries raise OperationalError: no such table.