web 應用、 框架 及HTTP協議

  

web 應用html

  1、web 應用程序是什麼前端

    Web應用程序是一種能夠經過Web訪問的應用程序,程序的最大好處是用戶很容易訪問應用程序,用戶只須要有瀏覽器便可,不須要再安裝其餘軟件python

    應用程序有兩種模式C/S、B/S。C/S是客戶端/服務器端程序,也就是說這類程序通常獨立運行。而B/S就是瀏覽器端/服務器端應用程序,這類應用程序通常藉助IE等瀏覽器來運行。WEB應用程序通常是B/S模式。Web應用程序首先是「應用程序」,和用標準的程序語言,如C、C++等編寫出來的程序沒有什麼本質上的不一樣。然而Web應用程序又有本身獨特的地方,就是它是基於Web的,而不是採用傳統方法運行的。換句話說,它是典型的瀏覽器/服務器架構的產物。mysql

    web應用程序的優勢web

    網絡應用程序不須要任何複雜的「展開」過程,你所須要的只是一個適用的瀏覽器;sql

    網絡應用程序一般耗費不多的用戶硬盤空間,或者一點都不耗費;數據庫

    它們不須要更新,由於全部新的特性都在服務器上執行,從而自動傳達到用戶端;django

    網絡應用程序和服務器端的網絡產品都很容易結合,如email功能和搜索功能;flask

    由於它們在網絡瀏覽器窗口中運行,因此大多數狀況下它們是經過跨平臺使用的 (例如Windows,Mac,Linux等等)。後端

    Web應用程序的缺點 

    網絡應用程序強調瀏覽器的適應性。若是瀏覽器方沒有提供特定的功能,或者棄用特定的平臺或操做系統版本(致使不適應),就會影響大量的用戶:

    網絡應用依靠互聯網遠程服務器端的應用文件。所以,當鏈接出問題時,應用將不能正常使用。

    許多網絡應用程序不是開源的,只能依賴第三方提供的服務,所以不能針對用戶定製化、個性化,並且大多數狀況下用戶不能離線使用,於是損失了不少靈活性

    它們徹底依賴應用服務商的可及性。若是公司倒閉,服務器中止使用,用戶也沒法追索之前的資料。對比而看,即便軟件製造商倒閉了,傳統的安裝軟件也能夠繼續運行,儘管不能再更新或有其餘用戶服務;

    類似地,提供方公司對軟件和其功能有了更大的控制權。只要他們願意就能爲軟件添加新特性,即便用戶想等bugs先被解決再更新。跳過較差的軟件版本也不可能了。公司能夠強加不受歡迎的特性給用戶,也能夠隨意減小帶寬來削減開支。

    公司理論上能夠檢索任何的用戶行爲。這有可能引發隱私安全問題

    B/S架構優勢

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

    一、這種架構採用Internet上標準的通訊協議(一般是TCP/IP協議)做爲客戶機同服務器通訊的協議。這樣可使位於Internet任意位置的人都可以正常訪問服務器。對於服務器來講,經過相應的Web服務和數據庫服務能夠對數據進行處理。對外採用標準的通訊協議,以便共享數據。

 

    二、在服務器上對數據進行處理,就處理的結果生成網頁,以方便客戶端直接下載

     三、在客戶機上對數據的處理被進一步簡化,將瀏覽器做爲客戶端的應用程序,以實現對數據的顯示。再也不須要爲客戶端單獨編寫和安裝其餘類型的應用程序。這樣,在客戶端只須要安裝一套內置瀏覽器的操做系統,直接安裝一套瀏覽器,就能夠實現服務器上數據的訪問。而瀏覽器是計算機的標準設備

    本質上:瀏覽器是一個socket客戶端,服務器是一個socket服務端

  二 、基於socket寫一個web 應用

  py文件

import socket def server_run(): soc = socket.socket() soc.bind(('127.0.0.1', 8008)) soc.listen(5) while True: conn, addr = soc.accept() recv_data = conn.recv(1024) print(recv_data) # 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 動態網頁,字符串替換 import time now=time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) print(now) with open('index.html','r',encoding='utf-8') as f: data=f.read() data=data.replace('@@@',now) conn.send(('HTTP/1.1 200 OK\r\n\r\n%s'%data).encode('utf-8')) conn.close() if __name__ == '__main__': server_run()

 

  index.html 文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h2>@@@</h2>

<img src="https://gss2.bdstatic.com/9fo3dSag_xI4khGkpoWK1HF6hhy/baike/c0%3Dbaike92%2C5%2C5%2C92%2C30/sign=5e3814acf9edab64607f4592965fc4a6/14ce36d3d539b600c0c465d0eb50352ac65cb74b.jpg" alt="">
</body>
</html>

  3、手寫簡單的web框架

  websever

a socket服務端 b 根據url不一樣返回不一樣的內容 url---視圖函數 c 字符串返回給用戶 特殊字符替換 Web框架種類: a b c Tornado 別人的a b c django(a用的wsgiref) 別人a b 別人c flask(c用的jinja2) 另外一種分類: Django和其它 ''' import socket import pymysql def index(request): return '<img src="https://gss2.bdstatic.com/9fo3dSag_xI4khGkpoWK1HF6hhy/baike/c0%3Dbaike92%2C5%2C5%2C92%2C30/sign=5e3814acf9edab64607f4592965fc4a6/14ce36d3d539b600c0c465d0eb50352ac65cb74b.jpg"></img>' def login(request): with open('login.html','r',encoding='utf-8') as f : data=f.read() return data def time(request): import datetime now=datetime.datetime.now().strftime('%Y-%m-%d %X') with open('time.html','r',encoding='utf-8') as f : data=f.read() data=data.replace('@@time@@',now) return data def user_list(request): # 建立鏈接 conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123456', db='lqz') cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) cursor.execute("select id,name,password from user") user_list = cursor.fetchall() cursor.close() conn.close() tr_list=[] for row in user_list: tr='<tr><td>%s</td><td>%s</td><td>%s</td></tr>'%(row['id'],row['name'],row['password']) tr_list.append(tr) with open('user_list.html','r',encoding='utf-8') as f: data=f.read() data=data.replace('@@body@@',''.join(tr_list)) return data def user_list_new(request): # 建立鏈接 conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123456', db='lqz') cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) cursor.execute("select id,name,password from user") user_list = cursor.fetchall() cursor.close() conn.close() with open('user_list_new.html','r',encoding='utf-8') as f: data=f.read() from jinja2 import Template template=Template(data) response=template.render(user_list=user_list) # response=template.render({'user_list':user_list}) return response urls = [ ('/index', index), ('/login', login), ('/time', time), ('/user_list', user_list), ('/user_list_new', user_list_new), ] def run(): soc = socket.socket() soc.bind(('127.0.0.1', 8006)) soc.listen(5) while True: conn, port = soc.accept() data = conn.recv(1024) # data=data.decode('utf-8') print(data) data = str(data, encoding='utf-8') request_list = data.split('\r\n\r\n') head_list = request_list[0].split('\r\n') method, url, htt = head_list[0].split(' ') # conn.send(b'hello web') conn.send(b'HTTP/1.1 200 OK \r\n\r\n') print(url) func_name = None for u in urls: if url == u[0]: func_name = u[1] break if func_name: response = func_name(data) else: response = '404 not found' conn.send(response.encode('utf-8')) conn.close() if __name__ == '__main__': run()

 

  login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<form action="">
    <p>用戶名:<input type="text"></p>
    <p>密碼:<input type="password"></p>


</form>
</body>
</html>

 

  time.html

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

 

  user_list.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>用戶列表</title>
</head>
<body>

<table border="1">
    <thead>
        <tr>
            <th>id</th>
            <th>用戶名</th>
            <th>密碼</th>
        </tr>
    </thead>
    <tbody> @@body@@ </tbody>


</table>

</body>
</html>

 

  user_list_new

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>用戶列表</title>
</head>
<body>
<table border="1">
    <thead>
    <tr>
        <th>id</th>
        <th>name</th>
        <th>password</th>
    </tr>
    </thead>
    <tbody> {% for user in user_list%} <tr>
        <td>{{user.id}}</td>
        <td>{{user.name}}</td>
        <td>{{user.password}}</td>
    </tr> {%endfor%} </tbody>


</table>

</body>
</html>

 

  web 框架

  一 web 框架

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

    python三大主流web框架

      Django:大而全,自帶了不少功能模塊,相似於航空母艦 (缺點:有點笨重)
      Flask:短小精悍,自帶的功能模塊特別少,大部分都是依賴於第三方模塊(小而輕)
      Tornado:異步非阻塞 主要用在處理高io 多路複用的狀況 能夠寫遊戲後端

 

    wsgiref模塊

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

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

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

  wsgiref 應用

from wsgiref.simple_server import make_server def mya(environ, start_response): print(environ) start_response('200 OK', [('Content-Type', 'text/html')]) if environ.get('PATH_INFO') == '/index': with open('index.html','rb') as f: data=f.read() elif environ.get('PATH_INFO') == '/login': with open('login.html', 'rb') as f: data = f.read() else: data=b'<h1>Hello, web!</h1>'
    return [data] if __name__ == '__main__': myserver = make_server('', 8011, mya) print('監聽8010') myserver.serve_forever()

 

    2、手寫本身的web 框架

  models.py

    連接數據庫返回字典格式:
     cursor=pymysql.cursors.DictCursor

  建立數據表

import pymysql #鏈接數據庫
conn = pymysql.connect(host='127.0.0.1',port= 3306,user = 'root',passwd='123456',db='web') #db:庫名 #建立遊標
cur = conn.cursor() sql=''' create table userinfo( id INT PRIMARY KEY , name VARCHAR(32) , password VARCHAR(32) ) ''' cur.execute(sql) #提交
conn.commit() #關閉指針對象
cur.close() #關閉鏈接對象
conn.close()

  myserver.py  啓動文件

from wsgiref.simple_server import make_server from urls import url_patters def mya(environ, start_response): # print(environ)
    start_response('200 OK', [('Content-Type', 'text/html')]) func = None for item in url_patters: if item[0] == environ.get('PATH_INFO'): func = item[1] break
    if func: data = func(environ) return [data] else: return [b'404'] if __name__ == '__main__': myserver = make_server('', 8011, mya) print('監聽8010') myserver.serve_forever()

  urls.py  路由配置

from views import * url_patters = [ ('/login', login), ('/index', index), ('/time', time), ]

  views.py  視圖函數

def index(environ): with open('templates/index.html', 'rb') as f: data = f.read() return data def time(environ): import datetime now=datetime.datetime.now().strftime('%y-%m-%d %X') print(now) return now.encode('utf-8') from urllib.parse import parse_qs import pymysql def login(request): if request.get("REQUEST_METHOD") == "POST": try: request_body_size = int(request.get('CONTENT_LENGTH', 0)) except (ValueError): request_body_size = 0 request_body = request['wsgi.input'].read(request_body_size) data = parse_qs(request_body) user = data.get(b"user")[0].decode("utf8") pwd = data.get(b"pwd")[0].decode("utf8") # 鏈接數據庫
        conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123456', db='web')  # db:庫名
        # 建立遊標
        cur = conn.cursor() SQL = "select * from userinfo WHERE NAME ='%s' AND PASSWORD ='%s'" % (user, pwd) cur.execute(SQL) if cur.fetchone(): f = open("templates/backend.html", "rb") data = f.read() data = data.decode("utf8") return data.encode("utf8") else: print("OK456") return b"user or pwd is wrong"

    else: f = open("templates/login.html", "rb") data = f.read() f.close() return data

  tempaltes 

    backend.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body> 登陸成功 </body>
</html>

    index

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body> index </body>
</html>

  login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<h4>登陸頁面</h4>
<form action="http://127.0.0.1:8011/login" method="post"> 用戶名 <input type="text" name="user"> 密碼 <input type="text" name="pwd">
    <input type="submit">
</form>
</body>
</html>

  3、其餘socket服務端

'cgi': CGIServer, 'flup': FlupFCGIServer, 'wsgiref': WSGIRefServer, 'waitress': WaitressServer, 'cherrypy': CherryPyServer, 'paste': PasteServer, 'fapws3': FapwsServer, 'tornado': TornadoServer, 'gae': AppEngineServer, 'twisted': TwistedServer, 'diesel': DieselServer, 'meinheld': MeinheldServer, 'gunicorn': GunicornServer, 'eventlet': EventletServer, 'gevent': GeventServer, 'geventSocketIO':GeventSocketIOServer, 'rocket': RocketServer, 'bjoern' : BjoernServer, 'auto': AutoServer,

 

  都遵循一個協議wsgi(Web Server Gateway Interface web服務網關接口)

 

 HTTP 協議 

    超文本傳輸協議:規定了客戶端與服務端消息傳輸的格式

     四大特性:
        1.基於TCP/IP協議做用於應用層的協議
        2.基於請求響應
        3.無狀態
        4.無鏈接

     數據格式之請求:

         請求首行

         請求頭(一堆,k,v鍵值對)

         空

         請求體(post 請求攜帶的數據)

     數據格式之響應

          響應首行

          響應頭(一堆,k,v鍵值對)

          空

          響應體(post 請求攜帶的數據)

      響應狀態碼
        1XX 服務器已經成功接受到你的數據正在處理,你能夠繼續提交其餘數據
        2XX 請求成功 服務器已經將你請求的數據發送給你了
        3XX 重定向
        4XX 請求資源不存在
        5XX 服務器錯誤

      動靜態網頁
        靜態網頁:
          頁面上的數據都是寫死的,萬年不變
      動態網頁:
          頁面上的數據是從後端動態獲取的
          好比後端獲取當前時間
          後端獲取數據庫數據而後傳遞給前端頁面

     

      模板渲染
          後端生成的數據直接傳遞給前端頁面使用(而且前端頁面能夠靈活的操做改數據) >>> 模板語法

          模板渲染 模板語法須要依賴於第三方模塊
          pip install jinja2

        模板語法 jinja2支持前端直接使用相似於python的語法操做數據

<p>{{ user_dic }}</p>
    <p>{{ user_dic.name }}</p>
    <p>{{ user_dic['password'] }}</p>
    <p>{{ user_dic.get('name') }}</p> {% for user in user_dict %} <!--[{},{},{},{}]-->
        <tr>
            <td>{{ user.id }}</td>
            <td>{{ user.name }}</td>
            <td>{{ user.password }}</td>
        </tr> {% endfor %} 
相關文章
相關標籤/搜索