• <noscript id="e0iig"><kbd id="e0iig"></kbd></noscript>
  • <td id="e0iig"></td>
  • <option id="e0iig"></option>
  • <noscript id="e0iig"><source id="e0iig"></source></noscript>
  • python Django之Web框架本質 (2)

    標簽: django  mysql  html  

    一.Web應用本質

    為了了解Django的客戶端與服務端的交互原理,我們需要了解Web應用的本質方便以后更加的理解Django原理

    在Web應用中,服務器把網頁傳給瀏覽器,實際上就是把網頁的HTML代碼發送給瀏覽器,讓瀏覽器顯示出來。而瀏覽器和服務器之間的傳輸協議是HTTP。所以本質上就是:

    • 瀏覽器發送一個HTTP請求
    • 服務器收到請求,生成一個HTML文檔
    • 服務器把HTML文檔作為HTTP響應的Body發送給瀏覽器
    • 瀏覽器收到HTTP響應,從HTTP Body取出HTML文檔并顯示。

    而在http協議中,我們可以用socket來實現

    1.socket本質

    web服務器本質上可以認為是一段代碼,可以不斷的處理http協議的網絡請求,而http協議可以使用socket實現,并且http協議是一個無狀態的協議,即瀏覽器發起請求,服務器接收請求,然后給瀏覽器回復數據,然后斷開連接;那么可以用socket來實現一個最簡單的web服務器。

    • HTTP:
      無狀態、短連接
    • TCP:
      不斷開(socket連接)
    • 服務器把HTML文檔作為HTTP響應的Body發送給瀏覽器
    • WEB應用(網站)
      • 瀏覽器(socket客服端)
        在客戶端訪問網址后,通過ping 網址 轉化為ip地址進行訪問(默認監聽80端口)
      • 瀏覽器(socket服務端)
        1. 監聽ip和端口
        2. 收到客戶端傳來的數據
        3. 響應客戶端,發送響應數據
        4. 斷開客戶端連接

    示意如下:

    import socket
    sock = socket.socket()
    # 網頁和監聽端口(這里先默認本機端口的8080)
    sock.bind(('127.0.0.1',8080))
    # 等待五個用戶
    sock.listen(5)
    # 因為socket是TCP協議不斷開
    while True:
    	#等待
    	conn,addr= sock.accept()
    	# 有人來連接
    	# 獲取用戶發送的數據
    	data = conn.recv(8096)
    	# 回數據,轉字節
    	conn.send(b'123123')
    	# 斷開客戶端連接
    	conn.close()
    

    訪問127.0.0.1:8080

    示意如下:
    在這里插入圖片描述


    二.發送HTTP協議、響應


    1.HTTP協議

    在html中發送獲取數據都遵從著HTTP協議,隨著時間的變化一點一點的在改變,直到現在,我們可以通過socket發來的請求打印data來查看http發送的響應數據:

    print(data)
    #返回
    """
    響應頭
    狀態:200 OK
    'GET /(get請求數據默認放這) HTTP/1.1' \
    'Host: 127.0.0.1:8080' \
    'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:84.0) Gecko/20100101 Firefox/84.0' \
    'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8' \
    'Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2' \
    'Accept-Encoding: gzip, deflate' \
    'Connection: keep-alive' \
    'Upgrade-Insecure-Requests: 1'
    
    請求體:如果是post請求數據放這
    
    響應體
    'GET /favicon.ico HTTP/1.1' \
    'Host: 127.0.0.1:8080' \
    'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:84.0) Gecko/20100101 Firefox/84.0' \
    'Accept: image/webp,*/*' \
    'Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2' \
    'Accept-Encoding: gzip, deflate' \
    'Connection: keep-alive' \
    'Referer: http://127.0.0.1:8080/'
    
    
    """
    

    很顯然我們上面寫的代碼沒有根據HTTP的協議發送請求,應該遵循HTTP協議,用戶在頁面上看到的內容”字符串“(看到頁面效果,是由瀏覽器解析出來的)

    示意如下:

    import socket
    sock = socket.socket()
    # 網頁和監聽端口(這里先默認本機端口的8080)
    sock.bind(('127.0.0.1',8080))
    # 等待五個用戶
    sock.listen(5)
    # 因為socket是TCP協議不斷開
    while True:
    	#等待
    	conn,addr= sock.accept()
    	# 有人來連接
    	#1. 獲取用戶發送的數據
    	data = conn.recv(8096)
        
        # 4. 遵循http協議
    	conn.send(b'HTTP/1.1 200 OK\r\n\r\n')
    	# 5. 返回數據,轉字節
    	conn.send(b'123123')
    	# 6. 斷開客戶端連接
    	conn.close()
       
    



    2.HTTP發送響應

    但是我們目前怎么樣都只有一個頁面,不能像其他的網站一樣有多個頁面,所以我們要從客戶端發來的請求中拿到數據在做出響應在返回:

    1. 獲取用戶發送的數據
    2. 接收請求傳來的數據
    3. 分割數據
    4. 遵循http協議
    5. 返回相應數據,轉字節
    6. 斷開客戶端連接

    示意如下:

    import socket
    
    # 相應數據函數
    def f1(request):
        return b"f1"
    
    
    def f2(request):
        return b"f2"
    
    # 類似django的路由
    routers = [
        ('/xxx', f1),
        ('/ooo', f2),
    ]
    
    # 主函數
    def run():
        sock = socket.socket()
        # 網頁和監聽端口(這里先默認本機端口的8080)
        sock.bind(('127.0.0.1', 8080))
        # 等待五個用戶
        sock.listen(5)
        # 因為socket是TCP協議不斷開
        while True:
            # 等待
            conn, addr = sock.accept()
            # 有人來連接
            # 1. 獲取用戶發送的數據
            data = conn.recv(8096)
            # 2. 接收請求傳來的數據
            data = str(data, encoding='utf-8')
            # 3. 分割數據,請求頭,和請求體
            headers, bodys = data.split('\r\n\r\n')
            temp_list = headers.split('\r\n')
            # 獲取一.get請求 二.訪問url 三.請求體
            res, url, hea = temp_list[0].split(' ')
            func_name = None
            # 4. 遵循http協議
            conn.send(b'HTTP/1.1 200 OK\r\n\r\n')
            # 這時候打印的就是后綴的值
            print(url)
           	# 遍歷路由
            for item in routers:
                if item[0] == url:
                	# 判斷是否是該url返回函數地址
                    func_name = item[1]
                    break
            # 判斷函數是否存在
            if func_name:
                response = func_name(data)
            else:
                response = b"404 not found"
                
    		 # 5. 返回相應數據,轉字節
            conn.send(response)
            # 6. 斷開客戶端連接
            conn.close()
    
    
    if __name__ == '__main__':
        run()
    
    

    訪問127.0.0.1:8080

    示意如下:
    在這里插入圖片描述


    所以通過上面例子我們可以寫一個html然后渲染。

    靜態網頁

    因為如果想要數據庫實時動態產生,我們需要數據庫的幫助,不過在開始介紹前,我們先寫靜態網頁,首先在當前主目錄下創建兩個文件夾動態網頁和靜態網頁。用于區分一下動態網頁和靜態網頁。

    在靜態文件/index.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>
                    <tr>
                        <th>1</th>
                        <th>root</th>
                        <th>[email protected]</th>
                    </tr>
                </tbody>
            </table>
    </body>
    </html>
    

    在f1中定義函數如下:

    def f1(request)
    	 f=open('靜態網頁/index.html', 'rb')
    	    data=f.read()
    	    f.close()
    	    return data
    

    訪問127.0.0.1:8080/xxx

    示意如下:

    在這里插入圖片描述

    動態網頁

    在前面的文章有寫到操作數據庫的方法,種類很多這里我們使用pymysql來實現,如果沒看到這里的可以點開鏈接:點我!!!進行查看。

    1. 導入驅動程序
    pip install pymysql
    
    1. 創建數據庫連接
    import pymysql
    # 創建連接
    conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='xxx', db='myemployees')
    cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
    # 關閉
    cursor.close()
    conn.close()
    

    在這里我們把/ooo改成/userlist.htm為了告訴大家django的路由和這個很像

    routers = [
        ('/xxx', f1),
        ('/userlist.htm', f2),
    ]
    

    在動態網頁/userlist.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>
                    <tr>
                     @@content@@
                    </tr>
                </tbody>
            </table>
    </body>
    </html>
    

    因為返回的是字符串所以我們可以對字符串進行拼接成html看得懂的,然后在從html轉化為字節傳給瀏覽器。

    在f2中定義函數如下:

    def f2(request):
    # 創建連接
        conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123456', 		db='myemployees')
        cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
        # 在數據庫查詢數據
        cursor.execute("SELECT employee_id,first_name,phone_number FROM employees")
        # 獲取所有查到的數據
        user_list = cursor.fetchall()
        # 關閉
        cursor.close()
        conn.close()
        # 拼接
        content_list = []
        for row in user_list:
            tp = "<tr><td>%s</td><td>%s</td><td>%s</td></tr>" % (row['employee_id'], row['first_name'], row['phone_number'])
            # 添加進來
            content_list.append(tp)
        # 拼接到一起
        content = "".join(content_list)
        # 打開userlist.html
        f = open('動態網頁/userlist.html', 'r', encoding='utf-8')
        # 獲得字符串(模板的渲染)
        template = f.read()
        # 關閉
        f.close()
        # 把我之前在html寫的@@content@@修改
        data = template.replace('@@content@@', content)
        # 把寫好的字符串轉成字節的形式給瀏覽器渲染成可視化界面
        return bytes(data, encoding='utf-8')
    

    此時訪問127.0.0.1:8080/userlist.htm

    示意如下:
    在這里插入圖片描述


    三.jinja2模板渲染

    對于上面的一系列操作,相對麻煩,又要替換字符串,轉字節,還得自己拼接,這時python中就出來了一個模塊jinjia2,它可以幫助我們進行模板的渲染,而渲染的規則要和它一致

    1. 安裝jinja2模塊
    pip install jinja2
    
    1. 添加一個路由和函數
    routers = [
        ('/xxx', f1),
        ('/userlist.htm', f2),
        ('/host.html',f3),
    ]
    

    在動態網頁/host.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>
                    {% for row in user_list %}
                        <tr>
                            <td>{{ row.employee_id }}</td>
                            <td>{{ row.first_name }}</td>
                            <td>{{ row.phone_number }}</td>
                        </tr>
                    {% endfor %}
                </tbody>
            </table>
    </body>
    </html>
    

    在f3中定義函數如下:

    def f3(request):
        f = open('動態網頁/host.html', 'r', encoding='utf-8')
        # 獲得字符串(模板的渲染)
        data = f.read()
        # 關閉
        f.close()
        # 創建連接
        conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123456', db='myemployees')
        cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
        # 在數據庫查詢數據
        cursor.execute("SELECT employee_id,first_name,phone_number FROM employees")
        # 獲取所有查到的數據
        user_list = cursor.fetchall()
        # 關閉
        cursor.close()
        conn.close()
        # 使用jinja2渲染
        template=Template(data)
        data=template.render(user_list=user_list)
        # 上傳
        return data.encode('utf-8')
    

    此時訪問此時訪問127.0.0.1:8080/host.html

    示意如下:

    在這里插入圖片描述

    版權聲明:本文為weixin_45859193原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。
    本文鏈接:https://blog.csdn.net/weixin_45859193/article/details/112094210

    智能推薦

    Python的web框架Django的多應用路由設置(2)

     路由的設置  所有建立的應用,都需要到Django的setting中進行注冊。  之后就可以在新建的應用中也建立一個urls.py,并建立路由 然后把此文件通過include方法,放入總路由即可 Django下的urls.py  ...

    python的Django框架應用(2)

    原文鏈接:http://blog.csdn.net/qq_38776653/article/details/75045149 一、創建新的app(student) 1、全局路由規則和app路由規則建立聯系 由于上次沒有配置全局的路由規則或者沒有讓項目路由和app路由建立聯系,也可以直接寫在全局的路由規則里面,但是一旦多,將會造成混亂,不好調用。所以最好還是在每個app建立一個盛放路由規則的容器,即...

    python的Django框架應用(2)

    一、創建新的app(student) 1、全局路由規則和app路由規則建立聯系 由于上次沒有配置全局的路由規則或者沒有讓項目路由和app路由建立聯系,也可以直接寫在全局的路由規則里面,但是一旦多,將會造成混亂,不好調用。所以最好還是在每個app建立一個盛放路由規則的容器,即urls.py文件。 全局路由設置(myschool/urls.py) 2、在項目配置文件增加已安裝好的app的配置 修改增加...

    粗讀web框架之go gin和python django

    為什么引入web框架    web應用的本質 瀏覽器發送一個HTTP請求; 服務器收到請求,生成一個HTML文檔; 服務器把HTML文檔作為HTTP響應的Body發送給瀏覽器; 瀏覽器收到HTTP響應,從HTTP Body取出HTML文檔并顯示;    涉及的問題   解析http請求 找到對應的處理函數 生成并發送http響應 web框架工作流程...

    python--web框架:Django

    Django         Python下有許多款不同的 Web 框架,如: Django、Tornado、Flask 等多種.         Django是重量級選手中最有代表性的一位。許多成功的網站和APP都基于Django。Dja...

    猜你喜歡

    Python Web編程 Django框架

    一.Django的流程和命令行工具 1個Djongo項目的結構: 1.Django實現流程: url.py:jianshu.com/p/2fbafbddf4d2 Django每次修改,自動重啟 index.html: 2.Django的命令行工具...

    HTML中常用操作關于:頁面跳轉,空格

    1.頁面跳轉 2.空格的代替符...

    freemarker + ItextRender 根據模板生成PDF文件

    1. 制作模板 2. 獲取模板,并將所獲取的數據加載生成html文件 2. 生成PDF文件 其中由兩個地方需要注意,都是關于獲取文件路徑的問題,由于項目部署的時候是打包成jar包形式,所以在開發過程中時直接安照傳統的獲取方法沒有一點文件,但是當打包后部署,總是出錯。于是參考網上文章,先將文件讀出來到項目的臨時目錄下,然后再按正常方式加載該臨時文件; 還有一個問題至今沒有解決,就是關于生成PDF文件...

    電腦空間不夠了?教你一個小秒招快速清理 Docker 占用的磁盤空間!

    Docker 很占用空間,每當我們運行容器、拉取鏡像、部署應用、構建自己的鏡像時,我們的磁盤空間會被大量占用。 如果你也被這個問題所困擾,咱們就一起看一下 Docker 是如何使用磁盤空間的,以及如何回收。 docker 占用的空間可以通過下面的命令查看: TYPE 列出了docker 使用磁盤的 4 種類型: Images:所有鏡像占用的空間,包括拉取下來的鏡像,和本地構建的。 Con...

    requests實現全自動PPT模板

    http://www.1ppt.com/moban/ 可以免費的下載PPT模板,當然如果要人工一個個下,還是挺麻煩的,我們可以利用requests輕松下載 訪問這個主頁,我們可以看到下面的樣式 點每一個PPT模板的圖片,我們可以進入到詳細的信息頁面,翻到下面,我們可以看到對應的下載地址 點擊這個下載的按鈕,我們便可以下載對應的PPT壓縮包 那我們就開始做吧 首先,查看網頁的源代碼,我們可以看到每一...

    精品国产乱码久久久久久蜜桃不卡