第一章 Django框架——Web應用、HTTP協議、Web框架


第一章 Django框架——Web應用程序、HTTP協議、Web框架

 

一、Web應用程序

二、HTTP協議

三、Web框架

 

 

一、Web應用程序

什么是Web應用程序(what):

Web應用程序是一種可以通過Web訪問的應用程序,程序的最大好處是用戶很容易訪問應用程序,用戶只需要有瀏覽器即可,不需要再安裝其他軟件。

應用程序有兩種模式C/S、B/S。C/S是客戶端/服務器端程序,也就是說這類程序一般獨立運行。而B/S就是瀏覽器端/服務器端應用程序,這類應用程序一般借助IE等瀏覽器來運行。WEB應用程序一般是B/S模式。Web應用程序首先是“應用程序”,和用標准的程序語言,如C、C++等編寫出來的程序沒有什么本質上的不同。然而Web應用程序又有自己獨特的地方,就是它是基於Web的,而不是采用傳統方法運行的。換句話說,它是典型的瀏覽器/服務器架構的產物。

Web應用程序優點:

  • 網絡應用程序不需要任何復雜的“展開”過程,你所需要的只是一個適用的瀏覽器;
  • 網絡應用程序通常耗費很少的用戶硬盤空間,或者一點都不耗費;
  • 它們不需要更新,因為所有新的特性都在服務器上執行,從而自動傳達到用戶端;
  • 網絡應用程序和服務器端的網絡產品都很容易結合,如email功能和搜索功能;
  • 因為它們在網絡瀏覽器窗口中運行,所以大多數情況下它們是通過跨平台使用的 (例如Windows,Mac,Linux等等)

Web應用程序缺點:

  • 網絡應用程序強調瀏覽器的適用性。如果瀏覽器方沒有提供特定的功能,或者棄用特定的平台或操作系統版本(導致不適用),就會影響大量用戶;
  • 網絡應用依靠互聯網遠程服務器端的應用文件。因此,當連接出問題時,應用將不能正常使用。
  • 許多網絡應用程序不是開源的,只能依賴第三方提供的服務,因此不能針對用戶定制化、個性化,而且大多數情況下用戶不能離線使用,因而損失了很多靈活性;
  • 它們完全依賴應用服務商的可及性。如果公司倒閉,服務器停止使用,用戶也無法追索以前的資料。對比而看,即使軟件制造商倒閉了,傳統的安裝軟件也可以繼續運行,盡管不能再更新或有其他用戶服務;
  • 相似地,提供方公司對軟件和其功能有了更大的控制權。只要他們願意就能為軟件添加新特性,即使用戶想等bugs先被解決再更新。跳過較差的軟件版本也不可能了。公司可以強加不受歡迎的特性給用戶,也可以隨意減少帶寬來削減開支。
  • 公司理論上可以檢索任何的用戶行為。這有可能引起隱私安全問題。

B\S架構優點:

瀏覽器/服務器架構(Browser/Server,簡稱B/S)能夠很好地應用在廣域網上,成為越來越多的企業的選擇。瀏覽器/服務器架構相對於其他幾種應用程序體系結構,有如下3方面的優點:

 

  • 這種架構采用Internet上標准的通信協議(通常是TCP/IP協議)作為客戶機同服務器通信的協議。這樣可以使位於Internet任意位置的人都能夠正常訪問服務器。對於服務器來說,通過相應的Web服務和數據庫服務可以對數據進行處理。對外采用標准的通信協議,以便共享數據。
  • 在服務器上對數據進行處理,就處理的結果生成網頁,以方便客戶端直接下載。
  • 在客戶機上對數據的處理被進一步簡化,將瀏覽器作為客戶端的應用程序,以實現對數據的顯示。不再需要為客戶端單獨編寫和安裝其他類型的應用程序。這樣,在客戶端只需要安裝一套內置瀏覽器的操作系統,直接安裝一套瀏覽器,就可以實現服務器上數據的訪問。而瀏覽器是計算機的標准設備
  • 總結一下,本質上:瀏覽器是一個socket客戶端,服務器是一個socket服務端

基於socket寫一個Web應用

 python文件

import socket

soc = socket.socket()
soc.bind(('127.0.0.1',8001))
soc.listen(5)

while True:
    print('監聽8001端口......')
    conn,address = soc.accept()

    data = conn.recv(1024)
    #轉換成str類型
    data = str(data,encoding='utf-8')
    request_list = data.split('\r\n')
    first_list = request_list[0].split(' ')
    conn.send(b'HTTP/1.1 200 OK \r\n\r\n')
    # 1 直接在send里寫,發送給客戶端
    # conn.send(b'HTTP/1.1 200 OK\r\n\r\n<h1>hello web</h1><img src="https://gss2.bdstatic.com/9fo3dSag_xI4khGkpoWK1HF6hhy/baike/c0%3Dbaike92%2C5%2C5%2C92%2C30/sign=5e3814acf9edab64607f4592965fc4a6/14ce36d3d539b600c0c465d0eb50352ac65cb74b.jpg"></img>')
    # 2 打開一個html文件,發送給客戶端
    # with open('index.html','r',encoding='utf-8') as f:
    #     data=f.read()
    # conn.send(('HTTP/1.1 200 OK\r\n\r\n%s'%data).encode('utf-8'))
    # 3 動態網頁,字符串替換
    if first_list[1] == '/index':
        # conn.send('<h1>index</h1><img src="https://gss0.bdstatic.com/-4o3dSag_xI4khGkpoWK1HF6hhy/baike/c0%3Dbaike92%2C5%2C5%2C92%2C30/sign=775f519ac08065386fe7ac41f6b4ca21/fd039245d688d43f63d84526771ed21b0ff43bf5.jpg">'.encode('utf-8'))
        with open('index.html','rb') as f:
            data = f.read()
        conn.send(data)
    elif first_list[1] == '/two':
        with open('two.html','r',encoding='utf-8') as f:
            data = f.read()
        import datetime
        new = datetime.datetime.now().strftime('%Y-%m-%d %X')
        data = data.replace('@@time@@',new)
        conn.send(data.encode('utf-8'))
    else:
        conn.send(b'404')
    # print(data)
    conn.close()

'''
# 請求首行:請求類型  請求地址  請求協議
b'GET /index HTTP/1.1\r\n
# 請求頭
Host: 127.0.0.1:8001\r\n
Connection: keep-alive\r\n
Cache-Control: max-age=0\r\n
Upgrade-Insecure-Requests: 1\r\n
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.75 Safari/537.36\r\n
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8\r\n
Accept-Encoding: gzip, deflate, br\r\n
Accept-Language: zh-CN,zh;q=0.9\r\n\r\n'

#請求體
。。。。。
'''

實現一個簡單的Web框架

 html文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>我的網頁</title>
</head>
<body>
    <h1>index html</h1>
    <img src="https://gss0.bdstatic.com/-4o3dSag_xI4khGkpoWK1HF6hhy/baike/c0%3Dbaike92%2C5%2C5%2C92%2C30/sign=775f519ac08065386fe7ac41f6b4ca21/fd039245d688d43f63d84526771ed21b0ff43bf5.jpg">

</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>two</title>
</head>
<body>
    <h1>two</h1>
    <hr>
    <div>@@time@@</div>
</body>
</html>

 

 二、HTTP協議

 什么是HTTP協議(what):

HTTP協議是Hyper Text Transfer Protocol(超文本傳輸協議)的縮寫,是用於萬維網(WWW:World Wide Web )服務器與本地瀏覽器之間傳輸超文本的傳送協議。

HTTP是一個屬於應用層的面向對象的協議,由於其簡捷、快速的方式,適用於分布式超媒體信息系統。它於1990年提出,經過幾年的使用與發展,得到不斷地完善和擴展。HTTP協議工作於客戶端-服務端架構為上。瀏覽器作為HTTP客戶端通過URL向HTTP服務端即WEB服務器發送所有請求。Web服務器根據接收到的請求后,向客戶端發送響應信息。

 

 

HTTP協議特性:

1.基於TCP/IP協議之上的應用層協議

2.基於請求-響應模式

HTTP協議規定,請求從客戶端發出,最后服務器端響應該請求並 返回。換句話說,肯定是先從客戶端開始建立通信的,服務器端在沒有 接收到請求之前不會發送響應。

 

3.無狀態保存

HTTP是一種不保存狀態,即無狀態(stateless)協議。HTTP協議 自身不對請求和響應之間的通信狀態進行保存。也就是說在HTTP這個 級別,協議對於發送過的請求或響應都不做持久化處理。

 

使用HTTP協議,每當有新的請求發送時,就會有對應的新響應產 生。協議本身並不保留之前一切的請求或響應報文的信息。這是為了更快地處理大量事務,確保協議的可伸縮性,而特意把HTTP協議設計成 如此簡單的。可是,隨着Web的不斷發展,因無狀態而導致業務處理變得棘手 的情況增多了。比如,用戶登錄到一家購物網站,即使他跳轉到該站的 其他頁面后,也需要能繼續保持登錄狀態。針對這個實例,網站為了能 夠掌握是誰送出的請求,需要保存用戶的狀態。HTTP/1.1雖然是無狀態協議,但為了實現期望的保持狀態功能, 於是引入了Cookie技術。有了Cookie再用HTTP協議通信,就可以管 理狀態了。有關Cookie的詳細內容稍后講解。

4.無連接

無連接的含義是限制每次連接只處理一個請求。服務器處理完客戶的請求,並收到客戶的應答后,即斷開連接。采用這種方式可以節省傳輸時間。

 

HTTP請求協議與響應協議:

http協議包含由瀏覽器發送數據到服務器需要遵循的請求協議與服務器發送數據到瀏覽器需要遵循的請求協議。用於HTTP協議交互的信被為HTTP報文。請求端(客戶端)的HTTP報文 做請求報文,響應端(服務器端)的 做響應報文。HTTP報文本身是由多行數據構成的字 文本。

 

①請求協議

請求格式

 

請求方式

  • GET提交的數據會放在URL之后,以?分割URL和傳輸數據,參數之間以&相連,如EditBook?name=test1&id=123456. POST方法是把提交的數據放在HTTP包的請求體中.
  • GET提交的數據大小有限制(因為瀏覽器對URL的長度有限制),而POST方法提交的數據沒有限制.
  • GET與POST請求在服務端獲取請求數據方式不同。

②響應協議

響應格式

響應狀態碼

狀態碼的職 是當客戶端向服務器端發送請求時, 返回的請求 結果。借助狀態碼,用戶可以知道服務器端是正常 理了請求,還是出 現了 。狀態碼如200 OK,以3位數字和原因 成。數字中的 一位指定了響應 別,后兩位無分 。響應 別有以5種。

 總結:

 

URL簡介

統一資源定位符是對可以從互聯網上得到的資源的位置和訪問方法的一種簡潔的表示,是互聯網上標准資源的地址。互聯網上的每個文件都有一個唯一的URL,它包含的信息指出文件的位置以及瀏覽器應該怎么處理它

格式:協議://IP:端口(80)/路徑?name=lqz&age=18

?之前的是請求路徑,?之后的是請求數據部分

import socket


sock=socket.socket()
sock.bind(("127.0.0.1",8808))
sock.listen(5)

while 1:
    print("server waiting.....")
    conn,addr=sock.accept()
    data=conn.recv(1024)
    print("data", data)

    # 讀取html文件
    with open("login.html","rb") as f:
        data=f.read()

    conn.send((b"HTTP/1.1 200 OK\r\nContent-type:text/html\r\n\r\n%s"%data))
    conn.close()
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>



<form action="" method="post">
    用戶名 <input type="text" name="user">
    密碼 <input type="password" name="pwd">
    <input type="submit">
</form>

</body>
</html>

 

三、Web框架

 1.Web框架

Web框架(Web framework)是一種開發框架,用來支持動態網站、網絡應用和網絡服務的開發。這大多數的web框架提供了一套開發和部署網站的方式,也為web行為提供了一套通用的方法。web框架已經實現了很多功能,開發人員使用框架提供的方法並且完成自己的業務邏輯,就能快速開發web應用了。瀏覽器和服務器的是基於HTTP協議進行通信的。也可以說web框架就是在以上十幾行代碼基礎張擴展出來的,有很多簡單方便使用的方法,大大提高了開發的效率。

2.wsgiref模塊(把socket做了封裝)

最簡單的Web應用就是先把HTML用文件保存好,用一個現成的HTTP服務器軟件,接收用戶請求,從文件中讀取HTML,返回。

如果要動態生成HTML,就需要把上述步驟自己來實現。不過,接受HTTP請求、解析HTTP請求、發送HTTP響應都是苦力活,如果我們自己來寫這些底層代碼,還沒開始寫動態HTML呢,就得花個把月去讀HTTP規范。

正確的做法是底層代碼由專門的服務器軟件實現,我們用Python專注於生成HTML文檔。因為我們不希望接觸到TCP連接、HTTP原始請求和響應格式,所以,需要一個統一的接口協議來實現這樣的服務器軟件,讓我們專心用Python編寫Web業務。這個接口就是WSGI:Web Server Gateway Interface。而wsgiref模塊就是python基於wsgi協議開發的服務模塊。

相當於

from wsgiref.simple_server import make_server
import my_urls
from views import *


def my_server(environ,start_response):
    print(environ['PATH_INFO'])
    start_response('200 OK', [('Content-Type', 'text/html')])
    func = None
    for url in my_urls.urls:
        if url[0] == environ['PATH_INFO']:
            func = url[1]
            break
    if func:
        response = func(environ)
    else:
        response = error(environ)

    return [response.encode('utf-8'),]

if __name__ == '__main__':
    my = make_server('127.0.0.1',8002,my_server)
    my.serve_forever()
wsgirefWeb

 

3.自己的寫簡單的Web框架

from wsgiref.simple_server import make_server
import my_urls
from views import *


def my_server(environ,start_response):
    print(environ['PATH_INFO'])
    start_response('200 OK', [('Content-Type', 'text/html')])
    func = None
    for url in my_urls.urls:
        if url[0] == environ['PATH_INFO']:
            func = url[1]
            break
    if func:
        response = func(environ)
    else:
        response = error(environ)

    return [response.encode('utf-8'),]

if __name__ == '__main__':
    my = make_server('127.0.0.1',8002,my_server)
    my.serve_forever()
wsgirefWeb
import views

urls = [
    ('/index',views.index),
    ('/time',views.time),
    ('/user_list',views.user_list)
]
my_urls
import pymysql

def index(response):
    with open('templates/index.html','r',encoding='utf-8') as f :
        data = f.read()
    return data


def time(response):
    import datetime
    new = datetime.datetime.now().strftime('%Y-%m-%d %X')
    with open('templates/two.html','r',encoding='utf-8') as f :
        data = f.read()
    data = data.replace('@@time@@',new)
    return data

def user_list(response):
    conn = pymysql.connect(host = '127.0.0.1',port = 3306, database = 'db2',password = '')
    cursor = conn.cursor(cursor = pymysql.cursors.DictCursor)
    cursor.execute('select * from user')
    user_list = cursor.fetchall()
    print(user_list)



def error(response):
    return 'error404'
Views

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM