Prerequisites
Before diving into web frameworks, ensure you have:
- Python fundamentals (functions, modules, packages, OOP)
- Basic HTML/CSS/JavaScript knowledge
- MySQL installation and database creation
- Linux basics (for deployment)
Review: Python and PyCharm
What are Python and PyCharm, and how do they relate?
Python is an interpreter that reads code written in Python syntax and instructs the computer to execute it. PyCharm is essentially a sophisticated text editor with features like code completion, debugging tools, and one-click execution. Once you configure PyCharm with a Python interpreter, you gain access to intelligent code suggestions and streamlined execution.
Code correctness depends on actual execution results, not the IDE's indicators. Red underlines don't always mean errors—the final output determines whether code works correctly.
Ways to run Python code:
- Temporary execution: Enter Python interpreter directly in the terminal. Code disappears once the session closes. Useful for quick debugging of simple snippets.
- Permanent execution: Save code to a file for persistent storage. File extensions can be anything (.txt, .dat), though
.pyis the standard convention.
Running Python files requires:
- Path to the Python interpreter
- Path to the Python file
Environment Variables
If you encounter "'xxx' is not recognized as an internal or external command" errors, configure your system environment variables accordingly.
What is a Web Framework?
Web frameworks can be categorized into three levels based on necessity:
Building a Web Framework from Scratch
To understand what frameworks do internally, let's construct a minimal web server based on network programming concepts.
Key Concepts:
- Network programming enables information transfer over the internet
- B/S architecture is fundamentally a variation of C/S architecture
- HTTP/HTTPS (secure, encrypted) are communication protocols that define how data is exchanged
Basic Socket Server Implementation:
import socket
# Step 1: Create socket object
server = socket.socket()
# Step 2: Bind to address
# IP identifies any computer globally
# PORT identifies a specific program on that computer
# Together, IP+PORT locates any program on any computer
server.bind(('127.0.0.1', 8000))
# Step 3: Start listening
server.listen()
while True:
# Step 4: Accept connections
client_socket, client_address = server.accept()
# Step 5: Receive and send data
request = client_socket.recv(1024)
print(request)
client_socket.send(b'Hello')
# Step 6: Close connection
client_socket.close()
# Step 7: Shutdown server
server.close()
Run this code and visit 127.0.0.1:8000 in your browser. You'll encounter an error. Why does this happen?
The browser expects data in a specific format following the HTTP protocol. Without adhering to this protocol, communication fails.
HTTP-Compliant Implementation:
import socket
# Step 1: Create socket
server = socket.socket()
# Step 2: Bind address
server.bind(('127.0.0.1', 8000))
# Step 3: Listen for connections
server.listen()
while True:
# Step 4: Accept incoming requests
client_socket, client_address = server.accept()
# Step 5: Handle request
request = client_socket.recv(1024)
print(request)
# HTTP response header required
client_socket.send(b'HTTP/1.1 200 OK\r\n\r\n')
client_socket.send(b'<strong>Connection established</strong>')
# Step 6: Close connection
client_socket.close()
# Step 7: Shutdown
server.close()
With just a few lines, we have a working web server. Visiting 127.0.0.1:8000 displays content directly.
Dynamic Content Based on URL
Extracting the URL path:
import socket
server = socket.socket()
server.bind(('127.0.0.1', 8000))
server.listen()
while True:
client_socket, client_address = server.accept()
request = client_socket.recv(1024)
# Convert bytes to string, split by newline
request_lines = request.decode().split('\r\n')
# Extract the URL path from first line
# Format: "GET /path HTTP/1.1"
url_path = request_lines[0].split(' ')[1]
print(url_path)
client_socket.send(b'HTTP/1.1 200 OK\r\n\r\n')
if url_path == '/about':
client_socket.send(b'<h1>About Page</h1>')
elif url_path == '/contact':
client_socket.send(b'<h1>Contact Page</h1>')
else:
client_socket.send(b'<h1>404 Not Found</h1>')
client_socket.close()
server.close()
Refactoring for Scalability:
As routes grow, the if-elif chain becomes unwieldy. Let's use a data-driven approach:
import socket
def handle_about():
return b'<h1>About Page</h1>'
def handle_contact():
return b'<h1>Contact Page</h1>'
def handle_default():
return b'<h1>404 - Page Not Found</h1>'
# Route mapping table
routes = [
('/about', handle_about),
('/contact', handle_contact)
]
server = socket.socket()
server.bind(('127.0.0.1', 8000))
server.listen()
while True:
client_socket, client_address = server.accept()
request = client_socket.recv(1024)
request_lines = request.decode().split('\r\n')
url_path = request_lines[0].split(' ')[1]
client_socket.send(b'HTTP/1.1 200 OK\r\n\r\n')
response = handle_default()
for path, handler in routes:
if url_path == path:
response = handler()
break
client_socket.send(response)
client_socket.close()
server.close()
This pattern—mapping URLs to handler functions through a data structure—mirrors how modern web frameworks like Flask and Django internally route requests. The framework handles the socket communication and routing infrastructure, allowing developers to focus on writing business logic.