python Django之Web框架本質 (2)
一.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. 斷開客戶端連接
- 瀏覽器(socket客服端)
示意如下:
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()
示意如下:
二.發送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發送響應
但是我們目前怎么樣都只有一個頁面,不能像其他的網站一樣有多個頁面,所以我們要從客戶端發來的請求中拿到數據在做出響應在返回:
- 獲取用戶發送的數據
- 接收請求傳來的數據
- 分割數據
- 遵循http協議
- 返回相應數據,轉字節
- 斷開客戶端連接
示意如下:
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()
示意如下:
所以通過上面例子我們可以寫一個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
示意如下:
動態網頁
在前面的文章有寫到操作數據庫的方法,種類很多這里我們使用pymysql來實現,如果沒看到這里的可以點開鏈接:點我!!!進行查看。
- 導入驅動程序
pip install pymysql
- 創建數據庫連接
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,它可以幫助我們進行模板的渲染,而渲染的規則要和它一致
。
- 安裝jinja2模塊
pip install jinja2
- 添加一個路由和函數
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
示意如下:
智能推薦
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的命令行工具...
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壓縮包 那我們就開始做吧 首先,查看網頁的源代碼,我們可以看到每一...