python就业班 miniweb框架_mini-web框架
1. 框架概述
web框架是一個為web服務器提供服務的應用程序,專門負責處理用戶的動態資源請求.
靜態資源: 資源的內容是固定不變的.
動態資源: 資源的內容是動態變化, 數據是從數據庫獲取的.
靜態 web 服務器 使用 tcp 傳輸數據
1. 導包 socket
2. 創建一個 socket 對象, socket.socket()
端口復用(可選的)
3. 綁定 socket對象.bind((ip, 端口))
4. 監聽 socket對象.listen()
5. 等待連接 socket對象.accept()---> 阻塞等待客戶端連接,返回一個新的 socket 對象
6. 接收信息(請求報文) recv
7. 發送信息(響應報文) send
8. 關閉套接字 close()
------------------------------------------
web 服務器的工作流程
1. 在瀏覽器輸入 URL 網址
2. 瀏覽器會訪問 DNS 服務器, 做 DNS 解析, 將域名對應的 ip 進行返回
3. 和服務器建立連接(三次握手)
4. 發送請求報文
5. web 服務器接收瀏覽器發送報文, 解析報文, 判斷請求的資源是靜態資源還是動態資源
6. 如果是靜態資源, web 服務器自己處理,將內容返回
7. 如果是動態資源, 需要將請求交給 web 框架處理
8. web 框架根據 web 服務器發送的請求, 從模板庫中讀取需要的模版文件, 同時還需要中數據庫中查詢需要的數據, 將數據和模版文件進行整合,組成完整的數據
9. web 框架將整理后的數據和處理結果發送給 web 服務器
10. web 服務器根據 web 框架發送內容,組成響應報文,發送給瀏覽器
11. 瀏覽器將資源進行整合, 顯示內容
---5 7 8 9 10 寫代碼實現---
2. 搭建框架
1. 找到之前書寫的靜態 web 服務器的代碼, 作為 web 服務器使用
import socket
import threading
class HTTPWebServer(object):
def __init__(self):
# 1. 創建 socket
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 設置端口復用
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
# 2. 綁定端口和 ip
server_socket.bind(('', 8080))
# 3. 設置監聽
server_socket.listen(128)
self.server_socket = server_socket # 將這個 socket 作為實例屬性
def __del__(self): # 對象銷毀的時候調用 close() 方法
self.server_socket.close()
@staticmethod
def __handle_client_request(new_soc, client_ip_port):
# 5. 接收信息(HTTP 請求報文)
buf = new_soc.recv(4096) # 一次性報文
if buf:
# 打印請求報文
# print(buf.decode())
buf = buf.decode()
# 6. 發送信息(HTTP 響應報文)
# 響應行 協議的版本 狀態碼 狀態描述
response_line = "HTTP/1.1 200 OK\r\n"
# 響應頭
response_header = "Server:PY\r\nName:py40\r\n"
# 空行(\r\n)
# 響應體, 文件的內容, 讀取文件,將文件的內容作為響應體發送
file_name = buf.split(' ', 2)[1]
print(f"請求的資源為{file_name}")
# 訪問的資源是 / ---> index.html
if file_name == '/':
file_name = '/index.html'
try:
with open('static' + file_name, 'rb') as f: # rb, 讀取出來的直接是 bytes
data = f.read()
except FileNotFoundError:
with open('static/error.html', 'rb') as f:
data = f.read()
# 如果文件不存在, 修改響應行的狀態碼
response_line = "HTTP/1.1 404 Not Found\r\n"
response = (response_line + response_header + '\r\n').encode() + data
new_soc.send(response)
else:
print(f"{client_ip_port} 斷開連接...")
# 7. 關閉連接
new_soc.close()
def start(self):
# 4. 等待連接
print('服務已啟動,端口為 8080, 等待連接....')
while True:
new_socket, ip_port = self.server_socket.accept()
print(f"{ip_port} 建立連接......")
# 用戶連接之后,創建一個線程
sub_thread = threading.Thread(target=self.__handle_client_request, args=(new_socket, ip_port))
sub_thread.start()
if __name__ == '__main__':
# 創建對象
web = HTTPWebServer()
web.start() # 啟動服務器
2. 將 static 文件和 template 文件放到當天的代碼目錄中
3. 啟動 web 服務器, 訪問之前的靜態頁面, 能夠正常訪問
4. 修改 web 服務器的代碼
3. 動態資源判斷
判斷一個資源是不是動態資源, 只需要判斷資源是不是以 .html 結尾 字符串.endswith()
# 此時獲取到文件的資源路徑,需要判斷是靜態資源還是動態資源
if file_name.endswith('.html'):
"""動態資源, 交給框架處理"""
# 思考,框架如何知道請求的是哪個頁面 ---> 函數傳參
# 一般的方法, 將需要傳遞的數據組成字典傳遞
# 好處: 可以傳遞多個數據
env = {
'filename': file_name,
# 還可以傳遞其他參數,目前不需要
}
status, header, file_data = framework.handle_request(env)
response_line = "HTTP/1.1%s\r\n" % status
response_header = header
data = file_data.encode()
else:
"""靜態資源,web 服務器直接自己處理"""
try:
with open('static' + file_name, 'rb') as f: # rb, 讀取出來的直接是 bytes
data = f.read()
except FileNotFoundError:
with open('static/error.html', 'rb') as f:
data = f.read()
# 如果文件不存在, 修改響應行的狀態碼
response_line = "HTTP/1.1 404 Not Found\r\n"
4. 處理客戶端的動態資源請求創建web框架程序
接收web服務器的動態資源請求
處理web服務器的動態資源請求并把處理結果返回給web服務器
web服務器把處理結果組裝成響應報文發送給瀏覽器
web框架程序(framework.py)代碼:
"""miniweb框架,負責處理動態資源請求"""
import time
# 獲取首頁數據
def index():
# 響應狀態
status = "200 OK";
# 響應頭
response_header = [("Server", "PWS2.0")]
# 處理后的數據
data = time.ctime()
return status, response_header, data
# 沒有找到動態資源
def not_found():
# 響應狀態
status = "404 Not Found";
# 響應頭
response_header = [("Server", "PWS2.0")]
# 處理后的數據
data = "not found"
return status, response_header, data
# 處理動態資源請求
def handle_request(env):
# 獲取動態請求資源路徑
request_path = env["filename"]
print("接收到的動態資源請求:", request_path)
if request_path == "/index.html":
# 獲取首頁數據
result = index()
return result
else:
# 沒有找到動態資源
result = not_found()
return result
5. 路由列表開發
路由: 請求的 URL 到到處理的函數之間的關系
5.1 在路由列表添加路由
# 定義路由列表, 在列表中保存所有的請求資源和處理函數的對應關系(Django)
route_list = [
('/index.html', index), # 函數地址的引用, 不能加括號的
('/center.html', center)
]
def handle_request(env):
"""處理動態資源請求"""
# 1. 獲取web 服務器傳遞的參數
file_name = env['filename'] # 通過字典的key 取值
print(f'接收到要處理的動態資源是: {file_name}')
# 遍歷路由列表, 查找需要請求的資源是否在路由列表中
for route in route_list:
if file_name == route[0]:
func = route[1] # func 是一個函數
return func() # return route[1]()
else:
return not_found()
5.2 裝飾器方式的添加路由
route_list = []
def my_route(filename):
# 定義裝飾器
def decorator(fn):
# 添加路由
# route_list.append((filename, fn))
def inner():
return fn()
route_list.append((filename, inner))
return inner
return decorator
@my_route('/index.html')
def index(): # 視圖函數
"""專門用來處理首頁數據的"""
# 1. 從模板庫讀取 html 頁面
with open('template/index.html', 'r') as f:
file_data = f.read()
6. 數據庫準備將提前給到大家的 stock_db.sql 復制到 Ubuntu 桌面中
登錄 mysql 客戶端 mysql -uroot -pmysql
創建數據庫 create database stock_db charset=utf8;
使用這個數據庫use stock_db
導入 SQL 語句 source ~/Desktop/stock_db.sql
7. index 頁面處理從數據庫獲取數據
使用這個數據進行模版替換
# 獲取首頁數據
@route("/index.html")
def index():
# 響應狀態
status = "200 OK";
# 響應頭
response_header = [("Server", "PWS2.0")]
# 打開模板文件,讀取數據
with open("template/index.html", "r") as file:
file_data = file.read()
# 處理后的數據, 從數據庫查詢
conn = pymysql.connect(host="localhost",
port=3306,
user="root",
password="mysql",
database="stock_db",
charset="utf8")
# 獲取游標
cursor = conn.cursor()
# 查詢sql語句
sql = "select * from info;"
# 執行sql
cursor.execute(sql)
# 獲取結果集
result = cursor.fetchall()
print(result)
data = ""
for row in result:
data += '''
%s%s%s%s%s%s%s%s''' % row# 替換模板文件中的模板遍歷
result = file_data.replace("{%content%}", data)
return status, response_header, result
8. center 頁面處理
前后端分離后端程序員提供數據接口
前端程序員,在頁面 發送 Ajax 請求,獲取數據,解析數據,將數據顯示到頁面中
8.1 后端
# 個人中心數據接口開發
@route("/center_data.html")
def center_data():
# 響應狀態
status = "200 OK";
# 響應頭
response_header = [("Server", "PWS2.0"), ("Content-Type", "text/html;charset=utf-8")]
conn = pymysql.connect(host="localhost",
port=3306,
user="root",
password="mysql",
database="stock_db",
charset="utf8")
# 獲取游標
cursor = conn.cursor()
# 查詢sql語句
sql = '''select i.code, i.short, i.chg,i.turnover, i.price, i.highs, f.note_infofrom info as i inner join focus as f on i.id = f.info_id;'''
# 執行sql
cursor.execute(sql)
# 獲取結果集
result = cursor.fetchall()
# 關閉游標
cursor.close()
# 關閉數據庫連接
conn.close()
# 個人中心數據列表
center_data_list = list()
# 遍歷每一行數據轉成字典
for row in result:
# 創建空的字典
center_dict = dict()
center_dict["code"] = row[0]
center_dict["short"] = row[1]
center_dict["chg"] = row[2]
center_dict["turnover"] = row[3]
center_dict["price"] = str(row[4])
center_dict["highs"] = str(row[5])
center_dict["note_info"] = row[6]
# 添加每個字典信息
center_data_list.append(center_dict)
# 把列表字典轉成json字符串, 并在控制臺顯示
json_str = json.dumps(center_data_list,ensure_ascii=False)
print(json_str)
return status, response_header, json_str
代碼說明:json.dumps函數把字典轉成json字符串
函數的第一個參數表示要把指定對象轉成json字符串
參數的第二個參數ensure_ascii=False表示不使用ascii編碼,可以在控制臺顯示中文。
響應頭添加Content-Type表示指定數據的編碼格式
8.2 前端
// 發送ajax請求獲取個人中心頁面數據
$.get("center_data.html", function (data) {
var data_array = data;
// 獲取table標簽對象
var $table = $(".table")
for(var i = 0; i < data_array.length; i++){
// 獲取每一條對象
var center_obj= data_array[i];
var row_html= '
' +'
'+ center_obj.code +'' +'
'+ center_obj.short +'' +'
'+ center_obj.chg +'' +'
'+ center_obj.turnover +'' +'
'+ center_obj.price +'' +'
'+ center_obj.highs +'' +'
'+ center_obj.note_info +'' +'
修改 ';// 為table標簽添加每一行組裝的html數據
$table.append(row_html);
}
}, "json");
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的python就业班 miniweb框架_mini-web框架的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 科创板是市值申购吗?
- 下一篇: python快速排序算法循环_算法:快速