Django-開胃菜

第一篇:

一.web應用

web應用是什麼css

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

應用程序有兩種模式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方面的優勢:python

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

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

二 基於SOCKET寫一個web應用

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文件

<!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>

三.手擼web框架

import socket


"""
請求首行
b'GET / HTTP/1.1\r\n
請求頭(一大堆kv鍵值對)
Host: 127.0.0.1:8080\r\n
Connection: keep-alive\r\n
Upgrade-Insecure-Requests: 1\r\n
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36\r\n
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3\r\n
Accept-Encoding: gzip, deflate, br\r\n
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8\r\n
\r\n
請求體
'
"""
server = socket.socket()  # 不傳參數默認就是TCP協議
server.bind(('127.0.0.1',8080))
server.listen(5)


while True:
    print('-------------')
    conn, addr = server.accept()  # 阻塞 等待客戶端連接
    data = conn.recv(1024)
    # print(data)
    conn.send(b'HTTP/1.1 200 OK\r\n\r\n')
    # print(data)
    # 手動處理http數據獲取用戶訪問的路徑
    # print(data.decode('utf-8').split('\r\n')[0])
    # print(data.decode('utf-8').split('\r\n')[0].split(' ')[1])
    current_path = data.decode('utf-8').split('\r\n')[0].split(' ')[1]
    if current_path == '/index':
        # 路由匹配上以後返回index
        # conn.send(b'<h1>index</h1>')
        with open('index.html','rb') as f:
            conn.send(f.read())
    else:
        # 當匹配不上的時候統一返回404
        conn.send(b'404')
    conn.close()

對於真實開發中的python web程序來講,通常會分爲兩部分:服務器程序和應用程序。jquery

服務器程序負責對socket服務器進行封裝,並在請求到來時,對請求的各類數據進行整理。web

應用程序則負責具體的邏輯處理。爲了方便應用程序的開發,就出現了衆多的Web框架,例如:Django、Flask、web.py 等。不一樣的框架有不一樣的開發方式,可是不管如何,開發出的應用程序都要和服務器程序配合,才能爲用戶提供服務。sql

這樣,服務器程序就須要爲不一樣的框架提供不一樣的支持。這樣混亂的局面不管對於服務器仍是框架,都是很差的。對服務器來講,須要支持各類不一樣框架,對框架來講,只有支持它的服務器才能被開發出的應用使用。數據庫

這時候,標準化就變得尤其重要。咱們能夠設立一個標準,只要服務器程序支持這個標準,框架也支持這個標準,那麼他們就能夠配合使用。一旦標準肯定,雙方各自實現。這樣,服務器能夠支持更多支持標準的框架,框架也可使用更多支持標準的服務器。bootstrap

WSGI(Web Server Gateway Interface)就是一種規範,它定義了使用Python編寫的web應用程序與web服務器程序之間的接口格式,實現web應用程序與web服務器程序間的解耦。

經常使用的WSGI服務器有uwsgi、Gunicorn。而Python標準庫提供的獨立WSGI服務器叫wsgiref,Django開發環境用的就是這個模塊來作服務器。

咱們利用wsgiref模塊來替換咱們本身寫的web框架的socket server部分:

def run_server(environ, start_response):
    start_response('200 OK', [('Content-Type', 'text/html;charset=utf8'), ])  # 設置HTTP響應的狀態碼和頭信息
    url = environ['PATH_INFO']  # 取到用戶輸入的url
    func = None
    for i in list1:
        if i[0] == url:
            func = i[1]
            break
    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()

urls文件

from views import *

urls = [
    ('/index',index),
    ('/login',login),
    ('/reg',reg),
    ('/get_time',get_time),
    ('/get_user',get_user),
    ('/get_db',get_db),
]

views文件

import time
from jinja2 import Template
import pymysql


def index(env):
    return 'index'

def login(env):
    return 'login'

def reg(env):
    return 'reg'

def get_time(env):
    # 先獲取當前時間
    current_time = time.strftime('%Y-%m-%d %X')
    # 打開html文件讀取內容返回給客戶端
    with open(r'templates/get_time.html','r',encoding='utf-8') as f:
        data = f.read()
    # 由於是以r模式打開的文件,全部獲取到的內容就是一堆字符串
    res = data.replace('@@time@@',current_time)  # 字符串的替換
    return res

def get_user(env):

    with open(r'templates/get_user.html','r',encoding='utf-8') as f:
        data = f.read()
    tmp = Template(data)
    # 將字典傳遞給前端頁面 前端經過變量名user_dic就能夠獲取到該字典
    return tmp.render(user_dic={'name':"jason",'password':'123'})


def get_db(env):
    # 鏈接數據庫 獲取數據 渲染到前端頁面
    conn = pymysql.connect(
        host = '127.0.0.1',
        port = 3306,
        user = 'root',
        password = '123',
        database = 'day54',
        charset = 'utf8',
        autocommit = True
    )
    cursor = conn.cursor(pymysql.cursors.DictCursor)
    cursor.execute('select * from userinfo')
    user_dict= cursor.fetchall()  # [{},{},{},{}]
    with open(r'templates/get_db.html','r',encoding='utf-8') as f:
        data = f.read()
    tmp = Template(data)
    return tmp.render(user_dict=user_dict)

def error(env):
    return '404 error'

templates裏面的html文件

get_db.html

<!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.4.1/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container">
    <div class="row">
        <div class="col-md-8 col-md-offset-2">
            <table class="table table-hover table-striped table-bordered">
                <thead>
                    <tr>
                        <th>id</th>
                        <th>name</th>
                        <th>password</th>
                    </tr>
                </thead>
                <tbody>
                    {% for user in user_dict %}  <!--[{},{},{},{}]-->
                        <tr>
                            <td>{{ user.id }}</td>
                            <td>{{ user.name }}</td>
                            <td>{{ user.password }}</td>
                        </tr>
                    {% endfor %}
                </tbody>
            </table>


        </div>
    </div>
</div>
{{ user_dict }}  <!--[{},{},{},{}]-->

</body>
</html>

get_time.html

<!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.4.1/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
</head>
<body>
@@time@@
</body>
</html>

get_user.html

<!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.4.1/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
</head>
<body>
<p>{{ user_dic }}</p>
<p>{{ user_dic.name }}</p>
<p>{{ user_dic['password'] }}</p>
<p>{{ user_dic.get('name') }}</p>



</body>
</html>

第二篇 HTTP協議詳解

一.協議簡介

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)無鏈接

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

請求協議

請求格式:

請求方式: get與post請求

  • GET提交的數據會放在URL以後,以?分割URL和傳輸數據,參數之間以&相連,如EditBook?name=test1&id=123456. POST方法是把提交的數據放在HTTP包的請求體中.

  • GET提交的數據大小有限制(由於瀏覽器對URL的長度有限制),而POST方法提交的數據沒有限制.

  • GET與POST請求在服務端獲取請求數據方式不一樣。

    '''
        GET請求
        # 請求首行
        GET / HTTP/1.1\r\n
        # get請求後面的參數
        GET /?name=lqz&age=18 HTTP/1.1\r\n
        # 請求頭
        Host: 127.0.0.1:8008\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/65.0.3325.181 Safari/537.36\r\n
        Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8\r\nAccept-Encoding: gzip, deflate, br\r\n
        Accept-Language: zh-CN,zh;q=0.9\r\n
        Cookie: csrftoken=7xx6BxQDJ6KB0PM7qS8uTA892ACtooNbnnF4LDwlYk1Y7S7nTS81FBqwruizHsxF\r\n\r\n'
        # 請求體(get請求,請求體爲空)    
        '''
        '''
        POST請求
        # 請求首行
        POST /?name=lqz&age=18 HTTP/1.1\r\n
        # 請求頭
        Host: 127.0.0.1:8008\r\nConnection: keep-alive\r\nContent-Length: 21\r\nCache-Control: max-age=0\r\nOrigin: http://127.0.0.1:8008\r\nUpgrade-Insecure-Requests: 1\r\nContent-Type: application/x-www-form-urlencoded\r\nUser-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8\r\nReferer: http://127.0.0.1:8008/?name=lqz&age=18\r\nAccept-Encoding: gzip, deflate, br\r\nAccept-Language: zh-CN,zh;q=0.9\r\nCookie: csrftoken=7xx6BxQDJ6KB0PM7qS8uTA892ACtooNbnnF4LDwlYk1Y7S7nTS81FBqwruizHsxF\r\n\r\n
        # 請求體
        name=lqz&password=123'
    
        '''
    
    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()

借鑑https://www.cnblogs.com/liuqingzheng/articles/9523086.html#_label0https://www.cnblogs.com/Dominic-Ji/articles/10982272.html

相關文章
相關標籤/搜索