What is a Web Framework?
A web framework is the underlying structure that supports the creation and operation of web services. These services enable users to interact with web content by making requests, which are then processed and responded to by the server.
Why Build a Web Framework Manually?
Manual framework construction provides insight into the inner workings of tools like Django, enhancing your ability to utilize them effectively.
Prerequisites
- Socket programming
- HTTP request/response handling
Building a Basic Web Framework
1. Serving HTML Content
Modify the server to return HTML files by reading them as binary data:
import socket
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind(('127.0.0.1', 8080))
server_socket.listen()
while True:
connection, address = server_socket.accept()
request = connection.recv(8096)
connection.send(b"HTTP/1.1 200 OK\r\n\r\n")
with open("test.html", "rb") as file:
connection.send(file.read())
connection.close()
2. Handling Multiple Pages
Use request headers to dteermine the desired page:
import socket
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind(('127.0.0.1', 8080))
server_socket.listen()
def home_page():
with open('index.html','rb') as f:
return f.read()
def auth_page():
with open('login.html','rb') as f:
return f.read()
def signup_page():
with open('register.html','rb') as f:
return f.read()
route_map = {
"/index": home_page,
"/login": auth_page,
"/register": signup_page,
}
while True:
connection, address = server_socket.accept()
request = connection.recv(1024)
request_data = request.decode('utf-8')
path = request_data.split('\r\n')[0].split(' ')[1]
if path in route_map:
response = route_map[path]()
else:
response = b'404 Not Found'
connection.send(b'HTTP/1.1 200 OK\r\n\r\n')
connection.send(response)
connection.close()
3. Dynamic Time Display
Embed dynamic content using placeholder replacement:
# date.html
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
Current Time: @@ currentTime @@
</body>
</html>
# views.py
from datetime import datetime
def display_time():
current_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
with open('date.html', 'r', encoding='utf-8') as f:
template = f.read()
rendered = template.replace('@@ currentTime @@', current_time)
return rendered.encode("utf-8")
Enhancing with Python Modules
1. Using wsgiref
Replace low-level socket operations with wsgiref:
from wsgiref.simple_server import make_server
def home_page():
with open('index.html','rb') as f:
return f.read()
def auth_page():
with open('login.html','rb') as f:
return f.read()
def signup_page():
with open('register.html','rb') as f:
return f.read()
route_map = {
"/index": home_page,
"/login": auth_page,
"/register": signup_page,
}
def application(env, start_response):
url = env.get('PATH_INFO')
if url in route_map:
response = route_map[url]()
else:
response = b'404 Not Found'
start_response('200 OK', [])
return [response]
if __name__ == '__main__':
server = make_server('127.0.0.1', 8090, application)
server.serve_forever()
2. Modularizing the Code
Organize functionality into separate files:
# urls.py
route_map = {
"/index": home_page,
"/login": auth_page,
"/register": signup_page,
}
# views.py
def home_page():
with open('index.html','rb') as f:
return f.read()
def auth_page():
with open('login.html','rb') as f:
return f.read()
def signup_page():
with open('register.html','rb') as f:
return f.read()
3. Database Integration
Retrieve data from a database and render it in templates using Jinja2:
# template.html
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
<h1>{{ user.name }}</h1>
<h2>{{ user.age }}</h2>
</body>
</html>
# views.py
from jinja2 import Template
import pymysql
def fetch_user_data():
db = pymysql.connect(
host='localhost',
port=3306,
user='root',
password='',
db='test_db',
charset='utf8'
)
cursor = db.cursor(pymysql.cursors.DictCursor)
cursor.execute('SELECT * FROM users LIMIT 1')
user = cursor.fetchone()
db.close()
with open('template.html', 'r', encoding='utf-8') as f:
template = Template(f.read())
return template.render(user=user).encode('utf-8')
Getting Started with Django
Django is a high-level Python web framework. Follow these steps to set up a basic project:
1. Installation and Initial Setup
- Install Django:
pip install django - Create a new project:
django-admin startproject myproject - Add an app:
python manage.py startapp users
2. Configuring Django
Edit the settings.py file to include your app and configure template and static files:
# settings.py
INSTALLED_APPS = [
# ...
'users.apps.UsersConfig',
]
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')],
'APP_DIRS': True,
# ...
},
]
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static'),
]
3. Creating Views
Define views in your app to handle requests and return responses:
# users/views.py
from django.shortcuts import render, redirect, HttpResponse
def home(request):
return HttpResponse("Welcome to the Home Page!")
def profile(request):
user_data = {
'name': 'John Doe',
'age': 30
}
return render(request, 'user_profile.html', user_data)
4. URL Routing
Map URLs to views in your project's urls.py:
# myproject/urls.py
from django.urls import path
from users import views
urlpatterns = [
path('', views.home, name='home'),
path('profile/', views.profile, name='profile'),
]
5. Running the Server
Start the development server:
python manage.py runserver
Common Issues and Solutions
- UnicodeEncodeError: Rename your computer to use ASCII characters only.
- SyntaxError (Generator expression): Use Python 3.6 or higher to resolve compatibility issues.
Django Execution Flow
Django processes requests through the following steps:
- Request is received by the server.
- URL routing determines which view to execute.
- View logic processes the request and prepares a response.
- Response is sent back to the client.
View Response Types
Django offers three main methods for returning responses:
HttpResponse: For plain text or HTML content.render: For rendering templates with context data.redirect: For redirecting to another URL.