標籤:code 顯示 strftime 訪問 ESS war web架構 XML flask
Web架構本質:
Web應用本質上就是socket伺服器.而使用者的瀏覽器就是一個scoket用戶端
import socketsk = 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服務本質上就是這是幾行代碼基礎上擴充出來的,這段代碼就是他們的祖宗
使用者再瀏覽器中輸入網址,瀏覽器會像伺服器發送資料,那瀏覽器會發送什麼資料呢?
規定HTTP協議,以後瀏覽器發送請求資訊也好,伺服器響應,都按照這個規則來.
HTTP協議主要規定了用戶端和伺服器之間的通訊格式,那HTTP協議是怎麼規定訊息格式的呢?
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()
輸出:
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 socketsk = 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 socketsk = 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 ...
報這個錯誤通常是因為電腦名稱為中文,改成英文的電腦名稱重啟下電腦就可以了。
web架構原理