[TOC]css
Django基礎以前戲
HTTP協議(超文本協議)
四大特性
基於TCP/IP之上做用於應用層
基於請求響應
發是請求,給是響應html
無狀態
不保存用戶狀態,連一次就給忘了前端
無鏈接
eg:one night lovepython
數據格式
請求格式
請求首行(請求方式,協議版本等)mysql
請求頭(一大堆K:V鍵值對)jquery
\r\nweb
請求頭(真正的數據 發post請求的時候纔有 若是get請求不會有)sql
響應格式
響應首行數據庫
響應頭django
\r\n
響應體
響應狀態碼
用特定的數字表示一些數據
1xx:服務端已經接收到了你的數據 正在處理 你能夠提交其餘數據
2xx:服務端成功響應(200請求成功)
3xx:重定向
4xx:請求錯誤(404 請求資源不存在 403 拒絕訪問)
5xx:(服務器內部錯誤(500))
請求方式
get請求
朝別人要數據
post請求
向別人提交數據(eg:用戶登陸)
純手擼web框架
- 手動書寫socket
- 手動處理http格式數據
簡單c/s鏈接
#服務端 import socket server = socket.socket() server.bind(('127.0.0.1', 8081)) 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) conn.send(b'hello baby') conn.close()
稍微複雜web框架
客戶端請求什麼,就返回什麼,eg:客戶端發送http://127.0.0.1:8081/index
則服務器返回給客戶端index
import socket server = socket.socket() server.bind(('127.0.0.1', 8081)) server.listen(5) while True: conn,addr = server.accept() conn.send(b'HTTP/1.1 200 OK\r\n\r\n') data = conn.recv(1024) print(data) data = data.decode('utf8') current_path = data.split('\r\n')[0].split(' ')[1] print(current_path) if current_path == '/index': conn.send(b'index') #服務端還能夠打開html文件,將文件中的東西顯示給客戶端 # with open(r'index.html', 'rb') as f: # conn.send(f.read()) else: conn.send(b'404 error') conn.close()
基於wsgiref
若是我不想寫上面代碼中的socket鏈接和裏面的index等內容,客戶端發送100個不一樣的請求,我也不能手擼100遍啊!那也太累了吧,因此咱們就利用了wsgiref模塊,幫咱們操做起來更簡單和方便,咱們能夠把在wsgiref.py中的必要代碼寫在相對應的文件內,如下是各個文件中要放的東西。
urls.py 路由與視圖函數對象關係 views.py 放的是視圖函數(處理業務邏輯的) templates 模板文件夾(一堆html文件)
wsgiref.py文件
from wsgiref.simple_server import make_server from urls import urls from views import * def run(env,response): """ :param env: 請求相關的全部數據 :param response: 響應相關的全部數據 :return: """ response('200 OK',[]) current_path = env.get('PATH_INFO') #env裏面有 不少數據,咱們篩選有用的數據就行 # 先定義一個變量名 用來存儲後續匹配到的函數名 func = None # for循環 匹配後綴 for url in urls: if current_path == url[0]: func = url[1] # 一旦匹配成功 就將匹配到的函數名賦值給func變量 break # 主動結束匹配 # 判斷func是否有值 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) # 實時監聽該地址 只要有客戶端來鏈接 統一交給run函數去處理 server.serve_forever() # 啓動服務端,永遠等着客戶端來鏈接
urls.py
from views import * urls = [ ('/index',index), #第二個是函數,若是匹配成功,就去views.py中去找相應的函數去運行 ('/login',login), ('/xxx',xxx), ]
views.py
from urls import urls def index(env): return 'index' def login(env): return 'login' def error(env): return '404 error' def xxx(env): return 'xxx'
客戶端經過訪問服務器獲取字典
咱們這裏須要用到一個模塊jinja2
咱們須要先去下載這個模塊from jinja2 import Template
具體瞭解jinja2
請點擊連接https://www.cnblogs.com/yanjiayi098-001/p/11701150.html
wsgiref.py文件
from wsgiref.simple_server import make_server from urls import urls from views import * def run(env,response): """ :param env: 請求相關的全部數據 :param response: 響應相關的全部數據 :return: """ response('200 OK',[]) current_path = env.get('PATH_INFO') #env裏面有 不少數據,咱們篩選有用的數據就行 # 先定義一個變量名 用來存儲後續匹配到的函數名 func = None # for循環 匹配後綴 for url in urls: if current_path == url[0]: func = url[1] # 一旦匹配成功 就將匹配到的函數名賦值給func變量 break # 主動結束匹配 # 判斷func是否有值 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) # 實時監聽該地址 只要有客戶端來鏈接 統一交給run函數去處理 server.serve_forever() # 啓動服務端,永遠等着客戶端來鏈接
urls.py
urls = [ ('/get_user',get_user), #第二個是函數,若是匹配成功,就去views.py中去找相應的函數去運行 ]
views.py
def get_user(env): d = {'name':'jason','pwd':'123','hobby':['read','running','music']} with open(r'get_user.html','r',encoding='utf-8') as f: data = f.read() temp = Template(data) #將data數據傳給這個temp,作處理 res = temp.render(user=d) # 將字典d傳遞給前端頁面 頁面上經過變量名user就可以獲取到該字典 return res
get_user.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> #jinja2模塊,能夠對字典 進行如下取值,同時這是jinja變量取值 {{ }}的語法 <p>{{ user }}</p> <p>{{ user.name }}</p> <p>{{ user['pwd'] }}</p> <p>{{ user.get('hobby') }}</p> </body> </html>
動靜態頁面
靜態頁面:就是一個寫死的頁面
動態頁面:能夠經過更改後端的數據,來反應到瀏覽器的頁面上
eg:1.後端獲取當前時間展現到前端
2.後端獲取數據庫中的數據展現到前端
客戶端經過訪問服務器獲取當前時間
那麼若是用戶訪問服務端,則客戶端頁面就會顯示當前時間,這樣該怎麼作呢?
咱們要知道,頁面就是要用到html,若是時間寫在HTML,那麼經過編碼格式,他已經再也不是時間了,那麼怎樣將時間顯示在頁面呢?
作法:咱們要在wsgiref模塊的基礎上,先在html中寫一串特定的字符,在後端將這串html和獲取的時間做交換,具體看代碼
wsgiref.py文件
from wsgiref.simple_server import make_server from urls import urls from views import * def run(env,response): """ :param env: 請求相關的全部數據 :param response: 響應相關的全部數據 :return: """ response('200 OK',[]) current_path = env.get('PATH_INFO') #env裏面有 不少數據,咱們篩選有用的數據就行 # 先定義一個變量名 用來存儲後續匹配到的函數名 func = None # for循環 匹配後綴 for url in urls: if current_path == url[0]: func = url[1] # 一旦匹配成功 就將匹配到的函數名賦值給func變量 break # 主動結束匹配 # 判斷func是否有值 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) # 實時監聽該地址 只要有客戶端來鏈接 統一交給run函數去處理 server.serve_forever() # 啓動服務端,永遠等着客戶端來鏈接
urls.py
from views import * urls = [ ('/get_time',get_time), #第二個是函數,若是匹配成功,就去views.py中去找相應的函數去運行 ]
views.py
from urls import * from datetime import datetime def get_time(): current_time = datetime.now().strftime('%Y-%m-%d %X') with open(r'get_time.html','r',encoding='utf-8') as f: #這是一串字符串 data= f.read() data = data.replace('$$time$$',current_time) return data
get_time.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> $$time$$ </body> </html>
客戶端經過訪問服務器獲取數據庫數據
獲取數據庫數據如今就和獲取字典的方法差很少像了,只不過咱們須要建一個數據庫,經過連接數據庫,去數據庫裏面拿值
wsgiref.py文件
from wsgiref.simple_server import make_server from urls import urls from views import * def run(env,response): """ :param env: 請求相關的全部數據 :param response: 響應相關的全部數據 :return: """ response('200 OK',[]) current_path = env.get('PATH_INFO') #env裏面有 不少數據,咱們篩選有用的數據就行 # 先定義一個變量名 用來存儲後續匹配到的函數名 func = None # for循環 匹配後綴 for url in urls: if current_path == url[0]: func = url[1] # 一旦匹配成功 就將匹配到的函數名賦值給func變量 break # 主動結束匹配 # 判斷func是否有值 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) # 實時監聽該地址 只要有客戶端來鏈接 統一交給run函數去處理 server.serve_forever() # 啓動服務端,永遠等着客戶端來鏈接
urls.py
urls = [ ('/get_db',get_db), #第二個是函數,若是匹配成功,就去views.py中去找相應的函數去運行 ]
views.py
import pymysql def get_db(env): conn = pymysql.connect( host = '127.0.0.1', port = 3306, user = 'root', password = 'root', database = 'day56', charset = 'utf8', autocommit = True ) cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) sql = "select * from userinfo" cursor.execute(sql) #提交sql語句,這個出發的是執行的對象並非一個值 res = cursor.fetchall() print(res) with open(r'get_db.html','r',encoding='utf-8') as f: data = f.read() temp = Template(data) ret = temp.render(user_list = res) # 將字典d傳遞給前端頁面 頁面上經過變量名user就可以獲取到該字典 return ret
get_db.html
咱們這裏用到了bootstrap搭建頁面,這就是一個典型的動態頁面
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script> <link href="https://cdn.bootcss.com/twitter-bootstrap/3.3.1/css/bootstrap.min.css" rel="stylesheet"> <script src="https://cdn.bootcss.com/twitter-bootstrap/3.3.1/js/bootstrap.min.js"></script> </head> <body> <div class="container"> <div class="row"> <div class="col-md-8 col-md-offset-2"> <h1 class="text-center">用戶列表</h1> <table class="table table-bordered table-striped table-hover"> <thead> <tr> <th>id</th> <th>name</th> <th>pwd</th> </tr> </thead> <tbody> {% for user_dict in user_list %} <tr> <td>{{ user_dict.id }}</td> <td>{{ user_dict.name }}</td> <td>{{ user_dict.pwd }}</td> </tr> {% endfor %} </tbody> </table> </div> </div> </div> </body> </html>
python三大主流web框架
A:socket部分 B:路由與視圖函數對應關係 C:模板語法
Django | Flask | Tornado |
---|---|---|
大而全 自帶的功能特別多 相似於航空母艦<br/> 有時候過於笨重 | 小而精 自帶的功能特別少 相似於遊騎兵<br/>第三方的模塊特別多,若是將flask第三方模塊所有加起來 徹底能夠超過django<br/>比較依賴於第三方模塊 | 異步非阻塞<br/> 牛逼到能夠開發遊戲服務器 |
A用的別人的 wsgiref<br/> B本身寫的<br/> C本身寫的 | A用的別人的 werkzeug(基於wsgiref)<br/> B本身寫的<br/> C用的別人的 jinja2 | 三者全是本身寫的 |