Web框架本質:php
Web應用本質上就是socket服務器.而用戶的瀏覽器就是一個scoket客戶端html
import socket sk = socket.socket() sk.bind(("127.0.0.1", 80)) sk.listen() while True: conn, addr = sk.accept() data = conn.recv(8096) conn.send(b'ok') conn.close()
能夠說web服務本質上就是這是幾行代碼基礎上擴展出來的,這段代碼就是他們的祖宗python
用戶再瀏覽器中輸入網址,瀏覽器會像服務器發送數據,那瀏覽器會發送什麼數據呢?web
規定HTTP協議,之後瀏覽器發送請求信息也好,服務器響應,都按照這個規則來.數據庫
HTTP協議主要規定了客戶端和服務器之間的通訊格式,那HTTP協議是怎麼規定消息格式的呢?django
import socket sk = socket.socket() sk.bind(("127.0.0.1", 8000)) sk.listen() while True: conn, addr = sk.recv(8096) data = conn.recv(8096) print(data) conn.send(b'ok') conn.close()
輸出:flask
b'GET / HTTP/1.1\r\nHost: 127.0.0.1:8080\r\nConnection: keep-alive\r\nCache-Control: max-age=0\r\nUpgrade-Insecure-Requests: 1\r\nUser-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3355.4 Safari/537.36\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8\r\nAccept-Encoding: gzip, deflate, br\r\nAccept-Language: zh-CN,zh;q=0.9\r\nCookie: csrftoken=CtHePYARJOKNx5oNVwxIteOJXpNyJ29L4bW4506YoVqFaIFFaHm0EWDZqKmw6Jm8\r\n\r\n'
將\r\n替換成換行;瀏覽器
GET / HTTP/1.1 Host: 127.0.0.1:8080 Connection: keep-alive Cache-Control: max-age=0 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3355.4 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 Accept-Encoding: gzip, deflate, br Accept-Language: zh-CN,zh;q=0.9 Cookie: csrftoken=CtHePYARJOKNx5oNVwxIteOJXpNyJ29L4bW4506YoVqFaIFFaHm0EWDZqKmw6Jm8
HTTP協議對手法消息的格式要求服務器
每一個HTTP請求和響應都應遵循相同的格式, 一個HTTP包含Header和Boby兩部分,其中送Boby均可選的.網絡
HTTP響應的Header中有一個Content-Type表名響應的內容格式,他的值如text/html;charset=utf-8
text/html表示網頁,charset-utf-8表示編碼爲utf-8
HTTP GET請求的格式;
HTTP 響應的格式;
自定義web框架
import socket sk = socket.socket() sk.bind(("127.0.0.1", 8000)) sk.listen() while True: conn, addr = sk.accept() data = conn.recv(8096) # 給回覆的消息加上響應狀態行 conn.send(b'HTTP/1.1 200 ok\r\n\r\n') conn.send(b'ok') conn.close()
經過以上的代碼讓網頁可以動態的顯示
import socket sk = socket.socket() sk.bind(("127.0.0.1", 8080)) sk.listen() # 返回不一樣的內容部分封裝成不一樣的函數 def timer(): import time date = time.strftime("%Y-%m-%d %H:%M:%S") with open("time.html", 'r', encoding='utf-8') as f: ret = f.read() ret = ret.replace('time', date) return ret.encode("utf-8") # 定義一個url和實際要執行的函數的對應關係 list1 = [ ("/time/", timer) ] while True: # 等待鏈接 conn, addr = sk.accept() data = conn.recv(8000) url = data.decode("utf-8").split()[1] # 按照空格分割獲取路徑 conn.send(b'HTTP/1.1 200 ok\r\n\r\n') # 發送遵循的HTTP協議和回覆的狀態代碼 func = None for i in list1: if i[0] == url: # 瀏覽器發來的地址取出來的地址 /admin/ func = i[1] break if func: response = func() else: response = b'404 not found' # 發送相應函數的返回的值 conn.send(response) conn.close()
服務器和應用程序
對於python web來講: 會分爲兩部分: 服務器和應用程序.
服務器看程序負責對socket服務端進行封裝,並在請求到來的時候,對請求的各類數據進行整理
應用該程序則負責的邏輯處理,爲了方便應用程序的開發, 就會出現了衆多的lweb框架,例如django,flask,web.py等, 不一樣的框架有不一樣的開發方式,可是不管如何,可發出的應用程序都要和服務器程序配合,才能爲用戶提供服務
這樣,服務器程序就須要不一樣的框架提供不一樣的支持, 這樣混亂的局面不管對於服務器仍是框架, 都是很差的,對於服務區來講,須要支持各類不一樣框架,對框架來講,只有支持他的服務器猜能被開開發出應用使用.
這時候,標準化就尤其重要, 咱們能夠設立一個及標準,只要付擠程序支持這個標準,框架也支持這個標準,那麼他們就能夠配合使用,一旦標準肯定,雙方各自實現.這樣,服務器能夠支持個多支持標準的框架, 框架一個可使用更多支持標準的服務器
WSGI(web Server Gateway Interfase)就是一種規範,他定義了使用Python編寫的web應用程序與web服務器程序之間額接口格式,實現web應用程序與web服務器程序間的解耦
經常使用的WSGI服務器又uwsgi, Gunicorn.二Python標準庫提供的獨立WSGI服務叫wsgiref,Diando開發環境用的就是這個模塊來作的服務器
wsgiref
咱們利用wsgiref模塊來替換咱們本身寫的web框架的socket.server部分
''' 根據URL中不一樣的路徑返回不一樣的內容--函數進階 返回HTML頁面 讓頁面動態起來 wsgiref模塊版 ''' from wsgiref.simple_server import make_server # 將返回的不一樣的內容部分封裝成函數 def index(url): # 讀取index.html頁面的內容 with open('index.html', 'r', encoding='utf-8') as f: s = f.read() # 返回字節數據 return bytes(s, encoding='utf-8') def home(url): with open('home.html', 'r', encoding='utf-8') as f: s = f.read() return bytes(s, encoding='utf-8') def timer(url): import time with open('time.html', 'r', encoding='utf-8') as f: s = f.read() s = s.replace("time", time.strftime("%Y-%m-%d %H:%M:%S")) return bytes(s, encoding='utf-8') # 定義一個url和實際要執行的函數的對應關係 list1 = [ ('/index/', index), ('home/', home), ('/time/', timer) ] def run_server(environ, start_response): start_response('200 ok', [('Content-Type', 'text/html; charset=utf-8'), ]) # 設置HTTP響應狀態和頭信息 url = environ['PATH_INFO'] # 獲取用戶輸入的url func = None for i in list1: if i[0] == url: func = i[1] if func: response = func(url) else: response = b'404 not found' return [response, ] if __name__ == '__main__': httpd = make_server('127.0.0.1', 8090, run_server) print("8090......") httpd.serve_forever()
Django
安裝Django===(安裝django1.11.15)
pip3 install django==1.11.15
建立一個django項目:
django-admin startproject projectname
mysite/ ├── manage.py # 管理文件 └── mysite # 項目目錄 ├── __init__.py ├── settings.py # 配置 ├── urls.py # 路由 --> URL和函數的對應關係 └── wsgi.py # runserver命令就使用wsgiref模塊作簡單的web server
運行django項目
python manage.py runserver 127.0.0.1: 8000
模板文件配置
TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(BASE_DIR, "template")], # template文件夾位置 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }, ]
靜態文件配置:
STATIC_URL = '/static/' # HTML中使用的靜態文件前綴 STATICFILES_DIRS = [ os.path.join(BARSE_DIR, 'static'), # 靜態文件存放位置 ]
剛開始學習是時可在配置文件中禁用csrf中間件,方便表單提交測試
MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', # 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', ]
Django基礎必備的三件套:
from django.shortcuts import HttpResponse, render, redirect
HttpResponse
內部傳入一個字符串參數,返回給瀏覽器.
例如:
def index(request): # 業務邏輯代碼 return HttpResponse("OK")
render
除了request參數外還接受一個待渲染的模板文件和一個保存具體數據的字典參數.
將數據填充模板文件, 最後把結構返回給瀏覽器.(相似於咱們上面用到的jinja2)
例如:
def index(request): # 業務邏輯代碼 return render(request, "index.html", {"name": "alex", "hobby": ["燙頭", "泡吧"]})
redirect
接受一個url參數,表示跳轉到指定的url
例如:
def index(request): # 業務邏輯代碼 return redirect("/home/")
重定向是怎麼回事?
重定向(Redirect)就是經過各類方法將各類網絡請求從新定個方向轉到其餘位置
1,網站調整
2,網頁被移到一個新的地址
3,網頁擴展名改變(如應用須要把.php改爲.html或.shtml)
這種狀況下,若是不作重定向,則用戶收藏夾或搜索數據庫中舊地址只能訪問一個404錯誤信息,流量白白流失.
啓動django報錯
Django 啓動時報錯 UnicodeEncodeError ...
報這個錯誤一般是由於計算機名爲中文,改爲英文的計算機名重啓下電腦就能夠了。