純手擼Django框架html
https協議:前端
四大特性:python
1.HTTP是一個基於TCP/IP通訊協議來傳遞數據(HTML 文件, 圖片文件, 查詢結果等)。mysql
2.基於請求響應web
3.HTTP是無狀態:HTTP協議是無狀態協議。無狀態是指協議對於事務處理沒有記憶能力。缺乏狀態意味着若是後續處理須要前面的信息,則它必須重傳,這樣可能致使每次鏈接傳送的數據量增大。另外一方面,在服務器不須要先前信息時它的應答就較快。sql
4.HTTP是無鏈接:無鏈接的含義是限制每次鏈接只處理一個請求。服務器處理完客戶的請求,並收到客戶的應答後,即斷開鏈接。採用這種方式能夠節省傳輸時間。數據庫
數據格式 請求: 請求首行GET url HTTP/1.1 請求頭(一大堆k,v的鍵值對組成) \r\n 請求體 響應: 同上 響應狀態碼 1XX:服務器已接收到你的數據正在處理,你能夠繼續提交數據 2XX:請求成功,返回相應數據 3XX:重定向 4XX:請求不存在(404) 5XX:服務器錯誤
基於socket寫一個web應用服務器
import socket """ 請求首行 b'GET / HTTP/1.1\r\n 請求頭(一大堆kv鍵值對) Host: 127.0.0.1:8080\r\n Connection: keep-alive\r\n Upgrade-Insecure-Requests: 1\r\n User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36\r\n Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3\r\n Accept-Encoding: gzip, deflate, br\r\n Accept-Language: zh-CN,zh;q=0.9,en;q=0.8\r\n \r\n 請求體 """ server = socket.socket() # 不傳參數默認就是TCP協議 server.bind(('127.0.0.1',8080)) server.listen(5) while True: conn, addr = server.accept() # 阻塞 等待客戶端連接 data = conn.recv(1024) conn.send(b'HTTP/1.1 200 OK\r\n\r\n') print(data) # 手動處理http數據獲取用戶訪問的路徑 current_path = data.decode('utf-8').split('\r\n')[0].split(' ')[1] if current_path == '/index': # 路由匹配上以後返回index # conn.send(b'<h1>index</h1>') with open('index.html','rb') as f: conn.send(f.read()) else: # 當匹配不上的時候統一返回404 conn.send(b'404') conn.close()
利用 wsgiref 和 jinja2 模塊手擼Django框架app
from wsgiref.simple_server import make_server from urls import * def run(env,response): """ :param env: 請求相關的信息 :param response: 響應相關的信息 :return: """ print(env) # 是一個大字典 裏面裝了一堆處理好了的鍵值對數據 response('200 OK',[('username','jason'),('password','123')]) # 固定寫法 後面列表裏面一個個元祖會以響應頭kv鍵值對的形式返回給客戶端 # 獲取用戶訪問的路徑 current_path = env.get('PATH_INFO') # if current_path == '/index': # return [b'index'] # elif current_path == '/login': # return [b'login'] # 定義一個存儲函數名的變量名 func = None # 循環比對路由與試圖函數的映射關係 for url_map in urls: # url_map = ('/index',index) if current_path == url_map[0]: func = url_map[1] # 只要匹配成功 直接結束循環 break if func: res = func(env) else: res = error(env) return [res.encode('utf-8')] if __name__ == '__main__': server = make_server('127.0.0.1',8080,run) server.serve_forever()
urls.py框架
from views import * urls = [ ('/index',index), ('/login',login), ('/reg',reg), ('/get_time',get_time), ('/get_user',get_user), ('/get_db',get_db), ]
view.py
import time from jinja2 import Template import pymysql def index(env): return 'index' def login(env): return 'login' def reg(env): return 'reg' def get_time(env): # 先獲取當前時間 current_time = time.strftime('%Y-%m-%d %X') # 打開html文件讀取內容返回給客戶端 with open(r'templates/get_time.html','r',encoding='utf-8') as f: data = f.read() # 由於是以r模式打開的文件,全部獲取到的內容就是一堆字符串 res = data.replace('@@time@@',current_time) # 字符串的替換 return res def get_user(env): with open(r'templates/get_user.html','r',encoding='utf-8') as f: data = f.read() tmp = Template(data) # 將字典傳遞給前端頁面 前端經過變量名user_dic就能夠獲取到該字典 return tmp.render(user_dic={'name':"jason",'password':'123'}) def get_db(env): # 鏈接數據庫 獲取數據 渲染到前端頁面 conn = pymysql.connect( host = '127.0.0.1', port = 3306, user = 'root', password = '123', database = 'day54', charset = 'utf8', autocommit = True ) cursor = conn.cursor(pymysql.cursors.DictCursor) cursor.execute('select * from userinfo') user_dict= cursor.fetchall() # [{},{},{},{}] with open(r'templates/get_db.html','r',encoding='utf-8') as f: data = f.read() tmp = Template(data) return tmp.render(user_dict=user_dict) def error(env): return '404 error'
流程圖:
模板語法
{{}} 變量相關 {%%} 邏輯相關 {{ data }} {{ data.name }} {{ data['name'] }} {{ data.get('name') }} {% for user_dict in user_list%} [{},{},{}] {{ user_dict }} {% endfor %}