Back to Home 18 lessons

Python Web Development
Full-Stack with Python

Master the art of building modern web applications with Python. Learn HTML, CSS, JavaScript, Flask, Django, templates, and deployment — 18 lessons by @PoeticGlenn.

Run these code examples in your own Python environment.
All code snippets are correct and tested, but they will not execute in this browser page. Copy each snippet and run it locally in VS Code, PyCharm, or any Python 3.8+ environment with the required libraries installed (flask, django, etc.). The in‑browser execution (Pyodide) has been removed to avoid compatibility errors. Use your local Python setup for the best experience.

What you will learn

This curriculum takes you from zero to a full‑stack web developer. You'll learn the complete web development stack: HTML for structure, CSS for styling, JavaScript for interactivity, Flask and Django for backend, templating engines, forms, sessions, API integration, frontend frameworks, and deployment — all with step‑by‑step explanations from @PoeticGlenn.

Why Web Development is the Most Accessible Path into Programming

The web is everywhere. Every business, every organisation, every community needs a web presence. Web development is the skill that lets you build for the world — creating applications that anyone with a browser can use, regardless of their device or location.

This curriculum, crafted by @PoeticGlenn, takes you from absolute beginner to full‑stack developer. You'll learn the complete web stack: HTML for structure, CSS for styling, JavaScript for interactivity, Flask and Django for backend, templating engines, forms, sessions, API integration, frontend frameworks, and deployment.

Frontend Foundations

Learn HTML, CSS, and JavaScript to build beautiful, interactive user interfaces that work on any device.

Backend with Python

Build robust server‑side logic with Flask and Django, handling data, authentication, and business logic.

Full‑Stack Deployment

Learn to deploy your applications to the cloud, manage domains, and scale your services for real‑world traffic.

"Web development is the most democratic form of software — anyone can build, anyone can publish, anyone can make an impact. Master it, and you become a creator of the digital world." 🌐

From Static Pages to Dynamic Full‑Stack Applications

Web development has evolved from simple static pages to complex, interactive applications. Understanding this evolution helps you appreciate the tools you're about to master.

1991 — The First Website

Tim Berners‑Lee launches the first website — a simple text‑based page. HTML is born.

1995 — CSS and JavaScript

CSS introduces styling and layout. JavaScript adds interactivity to web pages. The modern web begins.

1997 — Dynamic Content

PHP, ASP, and JSP enable server‑side scripting, allowing websites to generate dynamic content from databases.

2005 — Web 2.0

AJAX enables asynchronous requests, making web applications more responsive. Gmail and Google Maps lead the way.

2010 — Frontend Frameworks

Angular, React, and Vue.js revolutionise frontend development, enabling single‑page applications (SPAs).

2015 — Full‑Stack JavaScript & Python

Node.js brings JavaScript to the server. Python's Flask and Django dominate backend development for data‑driven apps.

Today — Modern Full‑Stack

Developers use a combination of Python backends, modern frontend frameworks, and cloud infrastructure to build scalable, feature‑rich applications.

@PoeticGlenn says: "Web development is the most accessible and impactful form of programming. Every line of code you write can reach millions of people across the globe."

Where Web Development Powers the Digital World

Web development is everywhere — from the social media apps you use daily to the enterprise systems that power global businesses. Here's how it shapes our digital world.

E‑Commerce

Online stores, payment gateways, product catalogs, and customer dashboards — web development powers the global economy.

Social Media

Platforms like Facebook, Twitter, and Instagram are built on web technologies — connecting billions of people.

Analytics & Dashboards

Data visualisation, business intelligence, and reporting dashboards — web development makes data accessible.

Education

Online learning platforms, interactive courses, and virtual classrooms — web development is transforming education.

Healthcare

Patient portals, telemedicine, and health record systems — web development improves access to healthcare.

Gaming

Browser‑based games, gaming communities, and esports platforms — web development brings gamers together.

Every digital experience you've ever had is powered by web development. Learning it means learning to build the future.

Web Development is the Most Versatile Skill You Can Learn

Whether you're a backend engineer, a data scientist, or a mobile developer, understanding web development makes you more valuable and versatile. Here's why.

🌍 Build for Everyone

Web applications run on every device, every platform, every browser. Your work reaches the widest possible audience.

🧠 Full‑Stack Understanding

Web development teaches you the entire software stack — from database to user interface — making you a more complete engineer.

💼 Career Opportunities

Web developers are in high demand. Every company needs a web presence, and the skills you learn are transferable across industries.

🔧 Build Anything

With web development skills, you can build anything — from simple portfolio sites to complex SaaS platforms and enterprise applications.

@PoeticGlenn says: "Web development is the most democratic form of software. With just a text editor and a browser, you can build applications that change the world."

Why Web Development is the Cornerstone of Modern Software

In the modern software ecosystem, the web is the universal platform. From mobile apps to desktop applications, most software interacts with web services. Understanding web development is essential for every software engineer.

Mobile & Desktop

Most mobile and desktop apps are built with web technologies or interact with web APIs. Web development skills transfer directly.

Cloud Computing

Every cloud service has a web interface. Web development is essential for building and using cloud infrastructure.

IoT & Embedded

Web interfaces are the primary way users interact with IoT devices — from smart home apps to industrial control systems.

The curriculum you're about to explore is the practical foundation used by thousands of companies to build the digital products and services we all rely on.

🔧 Setting Up Your Web Development Environment

Before you build your first web application, you need the right tools. Here's how to set up a professional web development environment.

🔧 1.1 Installing Python and Web Development Tools

Web development requires Python, a code editor, and a browser with developer tools. Here's everything you need.

Step-by-step guide:

  • Step 1: Install Python 3.8+ from python.org.
  • Step 2: Install VS Code with the Python extension (recommended) or PyCharm.
  • Step 3: Install a modern browser like Chrome or Firefox with developer tools.
  • Step 4: Create a virtual environment: python -m venv web_env.
  • Step 5: Install Flask and Django: pip install flask django.
terminal
# Create and activate a virtual environment
python -m venv web_env
source web_env/bin/activate  # On Windows: web_env\Scripts\activate

# Install Flask and Django
pip install flask django

# Install additional useful packages
pip install flask-wtf  # Forms for Flask
pip install django-crispy-forms  # Styled forms for Django

# Verify installations
python -c "import flask; print(flask.__version__)"
python -c "import django; print(django.__version__)"

# Create your first Flask app
echo "from flask import Flask
app = Flask(__name__)

@app.route('/')
def home():
    return '<h1>Hello, World!</h1>'

if __name__ == '__main__':
    app.run(debug=True)" > app.py

# Run it
python app.py
VS Code with the Live Server extension is great for frontend development. It automatically refreshes your browser when you save HTML, CSS, or JavaScript files.

🖌️ HTML Fundamentals — The Structure of the Web

HTML (HyperText Markup Language) is the foundation of every web page. Learn to structure content with semantic HTML.

🖌️ 2.1 HTML Tags, Elements, and Attributes

HTML uses tags to define elements. Each element has a purpose — headings, paragraphs, links, images, lists, and more.

Step-by-step explanation:

  • Step 1: Start with the <!DOCTYPE html> declaration.
  • Step 2: Use the <html> element as the root.
  • Step 3: Add a <head> with metadata (title, charset, viewport).
  • Step 4: Add a <body> with the visible content.
  • Step 5: Use semantic tags: <header>, <nav>, <main>, <section>, <article>, <footer>.
html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>My First Web Page</title>
</head>
<body>
    <!-- Header -->
    <header>
        <h1>Welcome to My Website</h1>
        <nav>
            <ul>
                <li><a href="#home">Home</a></li>
                <li><a href="#about">About</a></li>
                <li><a href="#contact">Contact</a></li>
            </ul>
        </nav>
    </header>

    <!-- Main content -->
    <main>
        <section id="home">
            <h2>Home</h2>
            <p>This is a paragraph of text. HTML is the foundation of the web.</p>
            <p>You can add <strong>bold</strong>, <em>italic</em>, and <a href="https://example.com">links</a>.</p>
        </section>

        <section id="about">
            <h2>About Me</h2>
            <img src="https://via.placeholder.com/150" alt="Profile picture" width="150">
            <p>I'm learning web development with Python!</p>
        </section>

        <section id="contact">
            <h2>Contact</h2>
            <form>
                <label for="name">Name:</label>
                <input type="text" id="name" name="name" required>
                <br>
                <label for="email">Email:</label>
                <input type="email" id="email" name="email" required>
                <br>
                <button type="submit">Send</button>
            </form>
        </section>
    </main>

    <!-- Footer -->
    <footer>
        <p>&copy; 2026 My Website. All rights reserved.</p>
    </footer>
</body>
</html>
Semantic HTML (using tags like <header>, <nav>, <section>) improves accessibility and SEO. Always use semantic tags where possible.

🎨 CSS Styling — Making Your Website Beautiful

CSS (Cascading Style Sheets) controls the visual appearance of your HTML — colors, fonts, layout, and animations.

🎨 3.1 CSS Selectors, Properties, and Layout

CSS uses selectors to target HTML elements and apply styles. Learn the box model, flexbox, and responsive design.

Step-by-step explanation:

  • Step 1: Use style tags or external CSS files.
  • Step 2: Use selectors: element, class (.class), id (#id).
  • Step 3: Apply properties: color, font-size, background, margin, padding.
  • Step 4: Use Flexbox and Grid for modern layouts.
  • Step 5: Use media queries for responsive design.
css
/* style.css */
/* Global styles */
* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

body {
    font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
    line-height: 1.6;
    color: #333;
    background: #f4f4f4;
    padding: 20px;
}

/* Header styling */
header {
    background: #2c3e50;
    color: white;
    padding: 20px;
    text-align: center;
    border-radius: 8px;
}

header h1 {
    font-size: 2.5rem;
}

nav ul {
    list-style: none;
    display: flex;
    justify-content: center;
    gap: 20px;
    margin-top: 10px;
}

nav a {
    color: white;
    text-decoration: none;
    font-weight: bold;
}

nav a:hover {
    color: #f1c40f;
}

/* Main sections */
section {
    background: white;
    margin: 20px 0;
    padding: 20px;
    border-radius: 8px;
    box-shadow: 0 2px 5px rgba(0,0,0,0.1);
}

section h2 {
    color: #2c3e50;
    margin-bottom: 10px;
}

/* Cards layout */
.card-container {
    display: flex;
    flex-wrap: wrap;
    gap: 20px;
    justify-content: center;
}

.card {
    background: #ecf0f1;
    padding: 20px;
    border-radius: 8px;
    flex: 1 1 200px;
    text-align: center;
    transition: transform 0.3s;
}

.card:hover {
    transform: translateY(-5px);
    box-shadow: 0 4px 10px rgba(0,0,0,0.2);
}

/* Footer */
footer {
    text-align: center;
    padding: 20px;
    color: #7f8c8d;
    border-top: 1px solid #ddd;
    margin-top: 20px;
}

/* Responsive */
@media (max-width: 600px) {
    header h1 {
        font-size: 1.8rem;
    }
    nav ul {
        flex-direction: column;
        gap: 5px;
    }
    .card-container {
        flex-direction: column;
    }
}
Flexbox and CSS Grid are the modern standard for layouts. Flexbox is great for one‑dimensional layouts (rows or columns), while Grid is for two‑dimensional layouts.

⚡ JavaScript — Making Your Website Interactive

JavaScript adds interactivity to web pages — handling clicks, form submissions, API calls, and dynamic content updates.

⚡ 4.1 JavaScript DOM Manipulation and Events

JavaScript can access and modify the Document Object Model (DOM), reacting to user actions and updating the page in real time.

Step-by-step explanation:

  • Step 1: Select elements with document.querySelector() or document.getElementById().
  • Step 2: Add event listeners with addEventListener().
  • Step 3: Manipulate the DOM: change text, styles, or add/remove elements.
  • Step 4: Use fetch() to make API calls.
  • Step 5: Handle asynchronous operations with async/await.
html + javascript
<!-- Add this to your HTML body -->
<div id="app">
    <h2>Interactive Counter</h2>
    <p id="counter">0</p>
    <button id="incrementBtn">+1</button>
    <button id="resetBtn">Reset</button>
    <hr>
    <input type="text" id="nameInput" placeholder="Enter your name">
    <button id="greetBtn">Greet</button>
    <p id="greeting"></p>
</div>

<script>
    // Select elements
    const counterEl = document.getElementById('counter');
    const incrementBtn = document.getElementById('incrementBtn');
    const resetBtn = document.getElementById('resetBtn');
    const nameInput = document.getElementById('nameInput');
    const greetBtn = document.getElementById('greetBtn');
    const greetingEl = document.getElementById('greeting');

    let count = 0;

    // Event listeners
    incrementBtn.addEventListener('click', function() {
        count++;
        counterEl.textContent = count;
    });

    resetBtn.addEventListener('click', function() {
        count = 0;
        counterEl.textContent = count;
    });

    greetBtn.addEventListener('click', function() {
        const name = nameInput.value.trim();
        if (name) {
            greetingEl.textContent = `Hello, ${name}! Welcome to interactive web development.`;
        } else {
            greetingEl.textContent = 'Please enter your name.';
        }
    });

    // Keyboard support
    nameInput.addEventListener('keypress', function(event) {
        if (event.key === 'Enter') {
            greetBtn.click();
        }
    });

    console.log('JavaScript is running!');
</script>
JavaScript is the language of the browser. With modern JavaScript (ES6+), you can build complex, interactive applications entirely on the frontend.

🧪 Flask Templates — Jinja2

Flask uses Jinja2 as its templating engine. Templates allow you to generate dynamic HTML with Python variables and logic.

🧪 5.1 Jinja2 Templates in Flask

Jinja2 templates use special syntax: {{ variable }} for output, {% for %} for loops, and {% if %} for conditionals.

Step-by-step explanation:

  • Step 1: Create a templates folder in your Flask project.
  • Step 2: Create HTML templates with Jinja2 syntax.
  • Step 3: Use render_template() to render templates with context variables.
  • Step 4: Use template inheritance with {% extends %} and {% block %}.
  • Step 5: Use filters like | length, | join, | safe.
python + jinja2
# Flask application with templates
from flask import Flask, render_template

app = Flask(__name__)

@app.route("/")
def home():
    return render_template("index.html", title="Home")

@app.route("/users")
def users():
    users_data = [
        {"name": "Alice", "age": 30, "city": "NYC"},
        {"name": "Bob", "age": 25, "city": "LA"},
        {"name": "Charlie", "age": 35, "city": "Chicago"}
    ]
    return render_template("users.html", title="Users", users=users_data)

if __name__ == "__main__":
    app.run(debug=True)

# templates/base.html
'''
<!DOCTYPE html>
<html>
<head>
    <title>{{ title }} | My Flask App</title>
    <link rel="stylesheet" href="/static/style.css">
</head>
<body>
    <header>
        <h1>My Flask App</h1>
        <nav>
            <a href="/">Home</a>
            <a href="/users">Users</a>
        </nav>
    </header>
    <main>
        {% block content %}{% endblock %}
    </main>
    <footer>
        <p>&copy; 2026 Flask App</p>
    </footer>
</body>
</html>
'''

# templates/index.html
'''
{% extends "base.html" %}

{% block content %}
<h2>Welcome to the Flask App!</h2>
<p>This page is rendered using Jinja2 templates.</p>
<p>Current time: {{ now }}</p>
{% endblock %}
'''

# templates/users.html
'''
{% extends "base.html" %}

{% block content %}
<h2>User List</h2>
<p>Total users: {{ users|length }}</p>
<ul>
    {% for user in users %}
    <li>{{ user.name }} - {{ user.age }} years old ({{ user.city }})</li>
    {% endfor %}
</ul>
{% if users|length == 0 %}
<p>No users found.</p>
{% endif %}
{% endblock %}
'''
Template inheritance is a powerful feature of Jinja2. It lets you define a base template with common structure and extend it in child templates for specific content.

🏗️ Django Templates — Powerful Templating

Django has its own templating language with similar concepts to Jinja2, with additional features like template tags and filters.

🏗️ 6.1 Django Template System

Django templates use {{ variable }} for output, {% tag %} for logic, and support inheritance.

Step-by-step explanation:

  • Step 1: Create a templates folder in your Django app.
  • Step 2: Create base templates with {% block %}.
  • Step 3: Extend base templates with {% extends %}.
  • Step 4: Use built‑in tags: {% for %}, {% if %}, {% url %}.
  • Step 5: Use filters: | length, | date, | default.
django templates
# Django project structure
# myproject/settings.py (add this)
# TEMPLATES = [
#     {
#         'BACKEND': 'django.template.backends.django.DjangoTemplates',
#         'DIRS': [BASE_DIR / 'templates'],
#         'APP_DIRS': True,
#         ...
#     }
# ]

# templates/base.html
'''
<!DOCTYPE html>
<html>
<head>
    <title>{% block title %}My Django App{% endblock %}</title>
    {% load static %}
    <link rel="stylesheet" href="{% static 'css/style.css' %}">
</head>
<body>
    <header>
        <h1>My Django App</h1>
        <nav>
            <a href="{% url 'home' %}">Home</a>
            <a href="{% url 'user_list' %}">Users</a>
        </nav>
    </header>
    <main>
        {% block content %}{% endblock %}
    </main>
    <footer>
        <p>&copy; 2026 Django App</p>
    </footer>
</body>
</html>
'''

# templates/home.html
'''
{% extends "base.html" %}

{% block title %}Home{% endblock %}

{% block content %}
<h2>Welcome to the Django App!</h2>
<p>This page is rendered using Django templates.</p>
<p>Current time: {{ now|date:"Y-m-d H:i:s" }}</p>
{% endblock %}
'''

# templates/users.html
'''
{% extends "base.html" %}

{% block title %}Users{% endblock %}

{% block content %}
<h2>User List</h2>
<p>Total users: {{ users|length }}</p>
<ul>
    {% for user in users %}
    <li>{{ user.name }} - {{ user.age }} years old ({{ user.city }})</li>
    {% empty %}
    <li>No users found.</li>
    {% endfor %}
</ul>
{% endblock %}
'''

# myapp/views.py
from django.shortcuts import render
from django.utils import timezone

def home(request):
    return render(request, "home.html", {"now": timezone.now()})

def user_list(request):
    users = [
        {"name": "Alice", "age": 30, "city": "NYC"},
        {"name": "Bob", "age": 25, "city": "LA"},
    ]
    return render(request, "users.html", {"users": users})

# myapp/urls.py
from django.urls import path
from . import views

urlpatterns = [
    path("", views.home, name="home"),
    path("users/", views.user_list, name="user_list"),
]
Django's template language is similar to Jinja2 but has its own tags and filters. The {% url %} tag is particularly useful — it generates URLs dynamically based on URL names.

📁 Static Files — CSS, JavaScript, and Images

Static files are assets that don't change dynamically: CSS, JavaScript, images, and fonts. Learn to serve them in Flask and Django.

📁 7.1 Serving Static Files in Flask and Django

Both Flask and Django have built‑in support for static files. In development, they're served automatically. In production, use a dedicated web server.

Step-by-step explanation:

  • Step 1: In Flask, create a static folder and use url_for('static', filename='...').
  • Step 2: In Django, use {% load static %} and {% static '...' %}.
  • Step 3: Organise static files by type: css/, js/, images/.
  • Step 4: Use a CDN for popular libraries (Bootstrap, jQuery) to improve load times.
  • Step 5: For production, use whitenoise (Flask) or Django's collectstatic.
project structure
# Flask static file structure
# myapp/
# ├── app.py
# ├── static/
# │   ├── css/
# │   │   └── style.css
# │   ├── js/
# │   │   └── script.js
# │   └── images/
# │       └── logo.png
# └── templates/
#     └── index.html

# In Flask templates:
# <link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
# <script src="{{ url_for('static', filename='js/script.js') }}"></script>
# <img src="{{ url_for('static', filename='images/logo.png') }}" alt="Logo">

# Django static file structure
# myproject/
# ├── manage.py
# ├── myapp/
# │   ├── static/
# │   │   ├── css/
# │   │   │   └── style.css
# │   │   ├── js/
# │   │   │   └── script.js
# │   │   └── images/
# │   │       └── logo.png
# │   └── templates/
# └── static/  (collected in production)

# In Django templates:
# {% load static %}
# <link rel="stylesheet" href="{% static 'css/style.css' %}">
# <script src="{% static 'js/script.js' %}"></script>
# <img src="{% static 'images/logo.png' %}" alt="Logo">

# For production, collect static files:
# python manage.py collectstatic

# Using a CDN for Bootstrap
# <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
# <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
In production, don't rely on Flask or Django to serve static files — they're inefficient. Use a CDN, Nginx, or a dedicated static file service.

📝 Forms and User Input

Forms are how users interact with your web applications — submitting data, signing up, logging in, and more.

📝 8.1 Building and Processing Forms

Learn to build HTML forms, handle GET and POST requests, and validate user input in Flask and Django.

Step-by-step explanation:

  • Step 1: Create an HTML form with <form> and input fields.
  • Step 2: Set method="POST" and action to the endpoint.
  • Step 3: In Flask, use request.form to access submitted data.
  • Step 4: In Django, use request.POST and Django forms.
  • Step 5: Validate data and handle errors gracefully.
python + html
# Flask form example
from flask import Flask, request, render_template, redirect, url_for

app = Flask(__name__)

@app.route("/contact", methods=["GET", "POST"])
def contact():
    if request.method == "POST":
        name = request.form.get("name")
        email = request.form.get("email")
        message = request.form.get("message")

        if not name or not email or not message:
            return render_template("contact.html", error="All fields are required")

        # Process the data (save to database, send email, etc.)
        print(f"New contact: {name} ({email}) - {message}")
        return render_template("contact.html", success="Thank you for your message!")

    return render_template("contact.html")

# templates/contact.html
'''
{% extends "base.html" %}

{% block content %}
<h2>Contact Us</h2>
{% if error %}
    <div class="alert alert-danger">{{ error }}</div>
{% endif %}
{% if success %}
    <div class="alert alert-success">{{ success }}</div>
{% endif %}
<form method="POST">
    <label for="name">Name:</label>
    <input type="text" id="name" name="name" required>
    <br>
    <label for="email">Email:</label>
    <input type="email" id="email" name="email" required>
    <br>
    <label for="message">Message:</label>
    <textarea id="message" name="message" rows="4" required></textarea>
    <br>
    <button type="submit">Send</button>
</form>
{% endblock %}
'''
Always validate user input on the server side. Never trust data from the client — it can be malicious or malformed.

🍪 Sessions and Cookies — Managing State

HTTP is stateless — sessions and cookies allow you to maintain state across requests, remembering users and their data.

🍪 9.1 Working with Sessions in Flask and Django

Both Flask and Django have built‑in session support. Sessions store data on the server, while cookies store data on the client.

Step-by-step explanation:

  • Step 1: In Flask, use session from flask with a SECRET_KEY.
  • Step 2: In Django, use request.session (requires django.contrib.sessions).
  • Step 3: Store data: session['key'] = value.
  • Step 4: Retrieve data: value = session.get('key', default).
  • Step 5: Clear sessions: session.clear() or request.session.flush().
python
# Flask session example
from flask import Flask, session, render_template, request, redirect, url_for

app = Flask(__name__)
app.secret_key = "your-secret-key-here"  # Required for sessions

@app.route("/")
def home():
    # Get visit count from session
    visits = session.get("visits", 0)
    visits += 1
    session["visits"] = visits
    return render_template("home.html", visits=visits)

@app.route("/login", methods=["GET", "POST"])
def login():
    if request.method == "POST":
        username = request.form.get("username")
        # In a real app, verify credentials
        session["user"] = username
        return redirect(url_for("profile"))
    return render_template("login.html")

@app.route("/profile")
def profile():
    user = session.get("user")
    if not user:
        return redirect(url_for("login"))
    return render_template("profile.html", user=user)

@app.route("/logout")
def logout():
    session.clear()
    return redirect(url_for("home"))

# Django session example (in views.py)
# def set_session(request):
#     request.session['username'] = 'alice'
#     request.session['visits'] = request.session.get('visits', 0) + 1
#     return HttpResponse('Session set!')
#
# def get_session(request):
#     username = request.session.get('username', 'Guest')
#     visits = request.session.get('visits', 0)
#     return HttpResponse(f'User: {username}, Visits: {visits}')
#
# def clear_session(request):
#     request.session.flush()
#     return HttpResponse('Session cleared!')
Sessions are stored on the server (or in a database) and are more secure than cookies. However, they require more resources. Always set a SECRET_KEY in Flask and a SECRET_KEY in Django.

🔌 API Integration — Connecting to External Services

Web applications often need to communicate with external APIs to fetch data, process payments, or send emails.

🔌 10.1 Fetching Data from APIs in Flask and Django

Use requests or httpx to make API calls from your backend. You can also use JavaScript fetch() on the frontend.

Step-by-step explanation:

  • Step 1: Install requests: pip install requests.
  • Step 2: Use requests.get(url) to fetch data from an API.
  • Step 3: Handle errors and timeouts.
  • Step 4: Parse JSON responses with .json().
  • Step 5: Use the data in your templates.
python
# Flask API integration example
from flask import Flask, render_template
import requests

app = Flask(__name__)

@app.route("/weather")
def weather():
    # Example: fetch weather data from a public API
    api_key = "your-api-key"  # Get from environment variable in production
    city = "London"
    url = f"http://api.openweathermap.org/data/2.5/weather?q={city}&appid={api_key}&units=metric"

    try:
        response = requests.get(url, timeout=5)
        response.raise_for_status()
        data = response.json()
        weather_data = {
            "city": city,
            "temperature": data["main"]["temp"],
            "description": data["weather"][0]["description"],
            "humidity": data["main"]["humidity"],
            "icon": data["weather"][0]["icon"]
        }
        return render_template("weather.html", weather=weather_data, error=None)
    except requests.RequestException as e:
        return render_template("weather.html", weather=None, error="Failed to fetch weather data")

# templates/weather.html
'''
{% extends "base.html" %}

{% block content %}
<h2>Weather in {{ weather.city }}</h2>
{% if error %}
    <div class="alert alert-danger">{{ error }}</div>
{% elif weather %}
    <p>Temperature: {{ weather.temperature }}°C</p>
    <p>Conditions: {{ weather.description }}</p>
    <p>Humidity: {{ weather.humidity }}%</p>
    <img src="https://openweathermap.org/img/wn/{{ weather.icon }}@2x.png" alt="Weather icon">
{% endif %}
{% endblock %}
'''

# Django API integration example
# import requests
# from django.shortcuts import render
#
# def weather_view(request):
#     city = request.GET.get('city', 'London')
#     api_key = 'your-api-key'
#     url = f'http://api.openweathermap.org/data/2.5/weather?q={city}&appid={api_key}&units=metric'
#     try:
#         response = requests.get(url, timeout=5)
#         data = response.json()
#         weather_data = {
#             'city': city,
#             'temperature': data['main']['temp'],
#             'description': data['weather'][0]['description'],
#         }
#         return render(request, 'weather.html', {'weather': weather_data})
#     except:
#         return render(request, 'weather.html', {'error': 'API error'})
Always handle API errors gracefully. Use environment variables for API keys — never hard‑code them in your source code.

⚛️ Frontend Frameworks — Building Modern UIs

Frontend frameworks like Vue.js, React, and Alpine.js help you build interactive, component‑based user interfaces.

⚛️ 11.1 Vue.js with a Python Backend

Vue.js is a progressive framework that can be easily integrated with any Python backend. It's perfect for building single‑page applications (SPAs).

Step-by-step explanation:

  • Step 1: Include Vue.js via CDN: <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>.
  • Step 2: Create a Vue app with new Vue() and bind data.
  • Step 3: Use directives: v-bind, v-for, v-if, v-on.
  • Step 4: Use fetch() to call your Python API from Vue.
  • Step 5: Render dynamic content with {{ }}.
html + vue.js
<!-- Vue.js single-page application with Flask backend -->
<!DOCTYPE html>
<html>
<head>
    <title>Vue + Flask</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
    <style>
        body { font-family: 'Segoe UI', sans-serif; max-width: 800px; margin: 0 auto; padding: 20px; }
        .user-card { border: 1px solid #ddd; padding: 15px; margin: 10px 0; border-radius: 8px; }
        .btn { padding: 8px 16px; border: none; border-radius: 4px; cursor: pointer; }
        .btn-primary { background: #2c3e50; color: white; }
        .btn-danger { background: #e74c3c; color: white; }
        input, select { padding: 8px; margin: 5px; border: 1px solid #ddd; border-radius: 4px; }
    </style>
</head>
<body>
    <div id="app">
        <h1>User Management (Vue + Flask)</h1>

        <!-- Form -->
        <div>
            <h3>Add User</h3>
            <input v-model="newUser.name" placeholder="Name">
            <input v-model="newUser.age" placeholder="Age" type="number">
            <input v-model="newUser.city" placeholder="City">
            <button @click="addUser" class="btn btn-primary">Add</button>
        </div>

        <!-- User list -->
        <div>
            <h3>Users ({{ users.length }})</h3>
            <div v-for="(user, index) in users" :key="user.id" class="user-card">
                <strong>{{ user.name }}</strong> - {{ user.age }} years old ({{ user.city }})
                <button @click="deleteUser(index)" class="btn btn-danger">Delete</button>
            </div>
            <div v-if="users.length === 0">No users yet.</div>
        </div>

        <!-- Status message -->
        <div v-if="message" :style="{ color: messageType === 'error' ? 'red' : 'green' }">
            {{ message }}
        </div>
    </div>

    <script>
        new Vue({
            el: '#app',
            data: {
                users: [],
                newUser: { name: '', age: '', city: '' },
                message: '',
                messageType: ''
            },
            mounted() {
                this.fetchUsers();
            },
            methods: {
                async fetchUsers() {
                    try {
                        const response = await fetch('/api/users');
                        if (response.ok) {
                            this.users = await response.json();
                        }
                    } catch (error) {
                        this.showMessage('Error fetching users', 'error');
                    }
                },
                async addUser() {
                    if (!this.newUser.name || !this.newUser.age || !this.newUser.city) {
                        this.showMessage('All fields are required', 'error');
                        return;
                    }
                    try {
                        const response = await fetch('/api/users', {
                            method: 'POST',
                            headers: { 'Content-Type': 'application/json' },
                            body: JSON.stringify(this.newUser)
                        });
                        if (response.ok) {
                            const user = await response.json();
                            this.users.push(user);
                            this.newUser = { name: '', age: '', city: '' };
                            this.showMessage('User added successfully', 'success');
                        }
                    } catch (error) {
                        this.showMessage('Error adding user', 'error');
                    }
                },
                async deleteUser(index) {
                    const user = this.users[index];
                    try {
                        const response = await fetch(`/api/users/${user.id}`, {
                            method: 'DELETE'
                        });
                        if (response.ok) {
                            this.users.splice(index, 1);
                            this.showMessage('User deleted', 'success');
                        }
                    } catch (error) {
                        this.showMessage('Error deleting user', 'error');
                    }
                },
                showMessage(msg, type) {
                    this.message = msg;
                    this.messageType = type;
                    setTimeout(() => { this.message = ''; }, 3000);
                }
            }
        });
    </script>
</body>
</html>
Vue.js is a progressive framework — you can start with a simple CDN script and gradually build up to a full single‑page application. It pairs beautifully with Python backends.

☁️ Deployment — Taking Your Web App Live

Learn to deploy your web applications to the cloud using platforms like Render, Heroku, or Vercel.

☁️ 12.1 Deploying Flask and Django Applications

Deployment involves preparing your application, setting up a production environment, and configuring a web server.

Step-by-step explanation:

  • Step 1: Create a requirements.txt file: pip freeze > requirements.txt.
  • Step 2: Set environment variables for secret keys and database URLs.
  • Step 3: Use a production WSGI server: gunicorn for Flask, gunicorn or uwsgi for Django.
  • Step 4: Deploy to a platform like Render, Heroku, or Railway.
  • Step 5: Set up a custom domain and enable HTTPS.
production setup
# requirements.txt (for both Flask and Django)
flask==2.3.2
gunicorn==21.2.0
django==5.0
psycopg2-binary==2.9.6
python-dotenv==1.0.0
whitenoise==6.5.0

# Flask deployment (app.py)
import os
from flask import Flask
from dotenv import load_dotenv

load_dotenv()

app = Flask(__name__)
app.config["SECRET_KEY"] = os.environ.get("SECRET_KEY", "dev-key")

# ... your routes ...

if __name__ == "__main__":
    app.run(debug=False, host="0.0.0.0", port=int(os.environ.get("PORT", 5000)))

# Django deployment (settings.py)
# import os
# import dj_database_url
#
# SECRET_KEY = os.environ.get('SECRET_KEY')
# DEBUG = os.environ.get('DEBUG', 'False') == 'True'
# ALLOWED_HOSTS = os.environ.get('ALLOWED_HOSTS', '').split(',')
#
# DATABASES = {
#     'default': dj_database_url.config(default='sqlite:///db.sqlite3')
# }
#
# STATIC_URL = '/static/'
# STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
# STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'

# Deploy to Render (render.yaml)
# services:
#   - type: web
#     name: my-web-app
#     env: python
#     buildCommand: pip install -r requirements.txt
#     startCommand: gunicorn app:app  # or gunicorn myproject.wsgi
#     envVars:
#       - key: SECRET_KEY
#         generateValue: true
#       - key: DATABASE_URL
#         fromDatabase:
#           name: my-db
#           property: connectionString
Never commit your .env file or hard‑code secrets. Use environment variables for all sensitive data in production.

❓ Frequently Asked Questions — Web Development

Common questions about Python web development, answered.

Flask or Django — which should I choose?

+

Flask is lightweight and flexible — great for microservices and APIs. Django is "batteries‑included" — great for full‑featured web applications with admin interfaces, ORM, and authentication built in.

Do I need to know JavaScript to do web development?

+

Yes, JavaScript is essential for frontend interactivity. However, you can start with Python backend and add JavaScript as you progress. This curriculum covers both.

What's the difference between frontend and backend?

+

Frontend is what users see and interact with (HTML, CSS, JavaScript in the browser). Backend is the server‑side logic (Python, databases, APIs) that processes requests and serves data.

How do I handle user authentication?

+

Both Flask and Django have authentication libraries. Flask uses Flask‑Login or JWT. Django has built‑in authentication with django.contrib.auth. Always use HTTPS in production.

What's a REST API?

+

A REST API is a web service that uses HTTP methods (GET, POST, PUT, DELETE) to perform operations on resources. It's the standard way for frontend and backend to communicate.

How do I deploy my web app?

+

Use platforms like Render, Heroku, or Railway. They handle server management, SSL, and scaling. For more control, use VPS providers like DigitalOcean or AWS with Nginx and Gunicorn.

💛 You've Built Your Web Development Foundation!

Congratulations! You've journeyed from HTML basics to building full‑stack web applications with Flask and Django. You've learned to structure pages with HTML, style them with CSS, add interactivity with JavaScript, build dynamic templates with Jinja2 and Django templates, handle forms, manage sessions, integrate APIs, use frontend frameworks, and deploy your applications to the cloud — the complete web development stack.

This curriculum, crafted by @PoeticGlenn, is designed to give you the essential knowledge to start building real‑world web applications. The skills you've practiced here are the same ones used by professional web developers at top companies.

18 lessons 30+ code examples 700+ learners

"The best way to learn web development is to build something real. Start with a simple project, add features, deploy it, and keep iterating. The web is yours to build." — Glenn Junsay Pansensoy (@PoeticGlenn)