日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Django基础一之web框架的本质

發布時間:2024/9/30 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Django基础一之web框架的本质 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

我們可以這樣理解:所有的Web應用本質上就是一個socket服務端,而用戶的瀏覽器就是一個socket客戶端,基于請求做出響應,客戶都先請求,服務端做出對應的響應,按照http協議的請求協議發送請求,服務端按照http協議的響應協議來響應請求,這樣的網絡通信,我們就可以自己實現Web框架了。

通過對socket的學習,我們知道網絡通信,我們完全可以自己寫了,因為socket就是做網絡通信用的,下面我們就基于socket來自己實現一個web框架,寫一個web服務端,讓瀏覽器來請求,并通過自己的服務端把頁面返回給瀏覽器,瀏覽器渲染出我們想要的效果。

html文件內容如下,名稱為test.html:

--------------------------------------------------------------------注:如果你對python感興趣,我這有個學習Python基地,里面有很多學習資料,感興趣的+Q群:895817687--------------------------------------------------------------------<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>Title</title><link rel="icon" href="wechat.ico"> <!--直接寫在html頁面里面的css樣式是直接可以在瀏覽器上顯示的--><style>h1{background-color: green;color: white;}</style> </head> <body><h1>姑娘,你好,我是Jaden,請問約嗎?嘻嘻~~</h1> <!--直接寫在html頁面里面的img標簽的src屬性值如果是別人網站的地址(網絡地址)是直接可以在瀏覽器上顯示的--> <!--<img src="https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1550395461724&di=c2b971db12eef5d85aba410d1e2e8568&imgtype=0&src=http%3A%2F%2Fy0.ifengimg.com%2Fifengimcp%2Fpic%2F20140822%2Fd69e0188b714ee789e97_size87_w800_h1227.jpg" alt="">--> <!--如果都是網絡地址,那么只要你的電腦有網,就可以看到,不需要自己在后端寫對應的讀取文件,返回圖片文件信息的代碼,因為別人的網站就做了這個事情了--> <img src="meinv.png" alt="" width="100" height="100"> <!--如果你是本地的圖片想要返回給頁面,你需要對頁面上的關于這個圖片的請求要自己做出響應,這個src就是來你本地請求這個圖片,你只要將圖片信息讀取出來,返回給頁面,頁面拿到這個圖片的數據,就能夠渲染出來了,是不是很簡單--><!--直接寫在html頁面里面的js操作是直接可以在瀏覽器上顯示的--> <script>alert('這是我們第一個網頁') </script><script src="test.js"></script> </body> </html><!--再準備一個圖片,名稱為meinv.jpg,再準備一個ico文件,名稱為wechat.ico,其實就是個圖片文件,微信官網打開之后,在瀏覽器最上面能夠看到-->

然后開始寫我們的web框架,我們分這么幾步來寫:

一、簡單的web框架

創建一個python文件,內容如下,名稱為test.py:

import socket sk = socket.socket() sk.bind(('127.0.0.1',8001)) sk.listen() conn,addr = sk.accept() from_b_msg = conn.recv(1024) str_msg = from_b_msg.decode('utf-8') #socket是應用層和傳輸層之間的抽象層,每次都有協議,協議就是消息格式,那么傳輸層的消息格式我們不用管,因為socket幫我們搞定了,但是應用層的協議還是需要咱們自己遵守的,所以再給瀏覽器發送消息的時候,如果沒有按照應用層的消息格式來寫,那么你返回給瀏覽器的信息,瀏覽器是沒法識別的。而應用層的協議就是我們的HTTP協議,所以我們按照HTTP協議規定的消息格式來給瀏覽器返回消息就沒有問題了,關于HTTP我們會細說,首先看一下直接寫conn.send(b'hello')的效果,然后運行代碼,通過瀏覽器來訪問一下,然后再看這一句conn.send(b'HTTP/1.1 200 ok \r\n\r\nhello')的效果 #下面這句就是按照http協議來寫的 # conn.send(b'HTTP/1.1 200 ok \r\n\r\nhello') #上面這句還可以分成下面兩句來寫 conn.send(b'HTTP/1.1 200 ok \r\n\r\n') with open('test.html','rb') as f:f_data = f.read() conn.send(f_data)

但是我們知道,我們的css和js基本都是寫在本地的文件里面的啊,而且我們的圖片基本也是我們自己本地的啊,怎么辦,我們將上面我們提前準備好的js和css還有那個.ico結尾的圖片文件都準備好,來我們在來一個升級版的web框架,其實css、js、圖片等文件都叫做網站的靜態文件。

首先我們先看一個效果,如果我們直接將我們寫好的css和js還有.ico和圖片文件插入到我們的html頁面里面,就是下面這個html文件

<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>Title</title><link rel="stylesheet" href="test.css"><link rel="icon" href="wechat.ico"> </head> <body> <h1>姑娘,你好,我是Jaden,請問約嗎?嘻嘻~~</h1> <img src="meinv.png" alt="" width="100" height="100"> <script src="test.js"></script> </body> </html><!--css文件內容如下,名稱為test.css: -->h1{background-color: green;color: white;}<!-- js文件內容如下,名稱為test.js:-->alert('這是我們第一個網頁');

二、返回靜態文件的高級web框架

import socketsk = socket.socket() sk.bind(('127.0.0.1',8001)) sk.listen()#首先瀏覽器相當于給我們發送了多個請求,一個是請求我們的html文件,而我們的html文件里面的引入文件的標簽又給我們這個網站發送了請求靜態文件的請求,所以我們要將建立連接的過程循環起來,才能接受多個請求,沒毛病 while 1:conn,addr = sk.accept()# while 1:from_b_msg = conn.recv(1024)str_msg = from_b_msg.decode('utf-8')#通過http協議我們知道,瀏覽器請求的時候,有一個請求內容的路徑,通過對請求信息的分析,這個路徑我們在請求的所有請求信息中可以提煉出來,下面的path就是我們提煉出來的路徑path = str_msg.split('\r\n')[0].split(' ')[1]print('path>>>',path)conn.send(b'HTTP/1.1 200 ok \r\n\r\n')#由于整個頁面需要html、css、js、圖片等一系列的文件,所以我們都需要給人家瀏覽器發送過去,瀏覽器才能有這些文件,才能很好的渲染你的頁面#根據不同的路徑來返回響應的內容if path == '/': #返回html文件print(from_b_msg)with open('test.html','rb') as f:# with open('Python開發.html','rb') as f:data = f.read()conn.send(data)conn.close()elif path == '/meinv.png': #返回圖片with open('meinv.png','rb') as f:pic_data = f.read()# conn.send(b'HTTP/1.1 200 ok \r\n\r\n')conn.send(pic_data)conn.close()elif path == '/test.css': #返回css文件with open('test.css','rb') as f:css_data = f.read()conn.send(css_data)conn.close()elif path == '/wechat.ico':#返回頁面的ico圖標with open('wechat.ico','rb') as f:ico_data = f.read()conn.send(ico_data)conn.close()elif path == '/test.js': #返回js文件with open('test.js','rb') as f:js_data = f.read()conn.send(js_data)conn.close()#注意:上面每一個請求處理完之后,都有一個conn.close()是因為,HTTP協議是短鏈接的,一次請求對應一次響應,這個請求就結束了,所以我們需要寫上close,不然瀏覽器自己斷了,你自己寫的服務端沒有斷,就會出問題。

完全搞定了,自己通過socket已經完全搞定了web項目,激動不,哈哈,我們再來完善一下

三、更高級版(函數+多線程版+動態獲取時間戳)web框架

# -*- coding: utf-8 -*- # @Time : 2019/7/12 17:11 # @Author : AnWen import time import socket from threading import Threadserver = socket.socket() server.bind(('127.0.0.1', 9000)) server.listen()def html(conn):time_msg=str(time.time())with open('test.html', 'r',encoding='utf-8') as f:date = f.read()# 在網頁中定義好特殊符號,用動態的數據去替換提前定義好的特殊符號date=date.replace('%這是被替換字符串%',time_msg)date=date.encode('utf-8')conn.send(date)conn.close()def css(conn):with open('test.css', 'rb') as f:date = f.read()conn.send(date)conn.close()def js(conn):with open('test.js', 'rb') as f:date = f.read()conn.send(date)conn.close()def ico(conn):with open('wechat.ico', 'rb') as f:date = f.read()conn.send(date)conn.close()def jpg(conn):with open('window.jpg', 'rb') as f:date = f.read()conn.send(date)conn.close()#定義一個路徑和執行函數的對應關系,不再寫一堆的if判斷了 urlpatterns = [('/', html),('/test.css', css),('/test.js', js),('/wechat.ico', ico),('/window.jpg', jpg) ]while True:conn, addr = server.accept()request_str = conn.recv(1024).decode('utf-8')path = request_str.split('\r\n')[0].split(' ')[1]print(path)# 因為要遵循HTTP協議,所以回復的消息也要加狀態行conn.send(b'HTTP/1.1 200 ok\r\n\r\n')#遍歷路徑和函數的對應關系列表,并開多線程高效的去執行路徑對應的函數,for item in urlpatterns:if path==item[0]:t=Thread(target=item[1],args=(conn,))t.start()

四、wsgiref模塊版web框架

wsgiref模塊其實就是將整個請求信息給封裝了起來,就不需要你自己處理了,假如它將所有請求信息封裝成了一個叫做request的對象,那么你直接request.path就能獲取到用戶這次請求的路徑,request.method就能獲取到本次用戶請求的請求方式(get還是post)等,那這個模塊用起來,我們再寫web框架是不是就簡單了好多啊。

對于真實開發中的python web程序來說,一般會分為兩部分:服務器程序和應用程序。

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

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

這樣,服務器程序就需要為不同的框架提供不同的支持。這樣混亂的局面無論對于服務器還是框架,都是不好的。對服務器來說,需要支持各種不同框架,對框架來說,只有支持它的服務器才能被開發出的應用使用。最簡單的Web應用就是先把HTML用文件保存好,用一個現成的HTTP服務器軟件,接收用戶請求,從文件中讀取HTML,返回。如果要動態生成HTML,就需要把上述步驟自己來實現。不過,接受HTTP請求、解析HTTP請求、發送HTTP響應都是苦力活,如果我們自己來寫這些底層代碼,還沒開始寫動態HTML呢,就得花個把月去讀HTTP規范。

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

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

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

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

好,接下來我們就看一下(能理解就行,了解就可以了):先看看wsfiref怎么使用:

from wsgiref.simple_server import make_server # wsgiref本身就是個web框架,提供了一些固定的功能(請求和響應信息的封裝,不需要我們自己寫原生的socket了也不需要咱們自己來完成請求信息的提取了,提取起來很方便) #函數名字隨便起 def application(environ, start_response):''':param environ: 是全部加工好的請求信息,加工成了一個字典,通過字典取值的方式就能拿到很多你想要拿到的信息:param start_response: 幫你封裝響應信息的(響應行和響應頭),注意下面的參數:return:'''start_response('200 OK', [('Content-Type', 'text/html'),('k1','v1')])print(environ)print(environ['PATH_INFO']) #輸入地址127.0.0.1:8080,這個打印的是'/',輸入的是127.0.0.1:8080/index,打印結果是'/index'return [b'<h1>Hello, web!</h1>']#和咱們學的socketserver那個模塊很像啊 httpd = make_server('127.0.0.1', 8080, application)print('Serving HTTP on port 8080...') # 開始監聽HTTP請求: httpd.serve_forever()

來一個完整的web項目,我們需要連接數據庫了,所以先到mysql數據庫里面準備一些表和數據

# -*- coding: utf-8 -*- # @Time : 2019/7/12 18:33 # @Author : AnWen import pymysqlconn = pymysql.connect(host='127.0.0.1',port=3306,user='root',password='123456',database='day53',charset='utf8', ) cursor = conn.cursor(pymysql.cursors.DictCursor) #創建表 sql = "create table userinfo(id int primary key auto_increment,name char(12),age int not null);" cursor.execute(sql) conn.commit() cursor.close() conn.close() import pymysql conn = pymysql.connect(host='127.0.0.1',port=3306,user='root',password='123456',database='day53',charset='utf8', ) cursor = conn.cursor(pymysql.cursors.DictCursor) #插入數據 sql = "insert into userinfo(name,age) values ('anwen',20);" cursor.execute(sql) conn.commit() cursor.close() conn.close() # -*- coding: utf-8 -*- # @Time : 2019/7/12 18:55 # @Author : AnWen import pymysql def showdata():conn = pymysql.connect(host='127.0.0.1',port=3306,user='root',password='123456',database='day53',charset='utf8',)cursor = conn.cursor(pymysql.cursors.DictCursor)#查詢數據sql = 'select * from userinfo'cursor.execute(sql)data=cursor.fetchone()conn.close()conn.cursor()return data # showdata()

wsgiref模塊版web框架

# -*- coding: utf-8 -*- # @Time : 2019/7/12 12:17 # @Author : AnWen import time from wsgiref.simple_server import make_server from showdata import showdatadef html():#獲取數據庫數據userinfo_data=showdata()# {'id': 1, 'name': 'anwen', 'age': 20}with open('test.html', 'r', encoding='utf-8') as f:date = f.read()date = date.replace('%這是被替換字符串%', userinfo_data['name'])date = date.encode('utf-8')return datedef css():with open('test.css', 'rb') as f:date = f.read()return datedef js():with open('test.js', 'rb') as f:date = f.read()return datedef ico():with open('wechat.ico', 'rb') as f:date = f.read()return datedef jpg():with open('window.jpg', 'rb') as f:date = f.read()return dateurlpatterns = [('/', html),('/test.css', css),('/test.js', js),('/wechat.ico', ico),('/window.jpg', jpg) ]def application(environ, start_response):''':param environ: 是全部加工好的請求信息,加工成了一個字典,通過字典取值的方式就能拿到很多你想要拿到的信息:param start_response: 幫你封裝響應信息的(響應行和響應頭),注意下面的參數:return:'''# print(environ)start_response('200 ok', [('k1', 'v1')])path = environ['PATH_INFO']for item in urlpatterns:if path == item[0]:ret = item[1]()breakelse:ret = '404 not found!'return [ret]httpd = make_server('127.0.0.1', 9000, application) print('Serving HTTP on port 9000...') # 開始監聽HTTP請求: httpd.serve_forever()# wsgiref本身就是個web框架,提供了一些固定的功能(請求和響應信息的封裝,不需要我們自己寫原生的socket了也不需要咱們自己來完成請求信息的提取了,提取起來很方便)

模板渲染JinJa2
上面的代碼實現了一個簡單的動態頁面(字符串替換),我完全可以從數據庫中查詢數據,然后去替換我html中的對應內容(專業名詞叫做模板渲染,你先渲染一下,再給瀏覽器進行渲染),然后再發送給瀏覽器完成渲染。 這個過程就相當于HTML模板渲染數據。 本質上就是HTML內容中利用一些特殊的符號來替換要展示的數據。 我這里用的特殊符號是我定義的,其實模板渲染有個現成的工具: jinja2

下載:pip install jinja2
使用jinja2渲染index2.html文件

<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>第一個Web框架</title><link rel="stylesheet" href="test.css"><link rel="icon" href="wechat.ico"> </head> <body> <h1>%這是被替換字符串%</h1> <h1>{{userinfo}}</h1> <!--<ul>--> <!-- {% for k,v in userinfo.items() %}--> <!-- <li>{{k}}&#45;&#45;{{v}}</li>--> <!-- {% endfor %}--> <!--</ul>--> <ul>{% for k,v in userinfo.items() %}<li>{{v}}</li>{% endfor %} </ul><h1>嘻嘻~~</h1> <img src="window.jpg" alt="" width="100px" height="100px"> <script src="test.js"></script> </body> </html> # -*- coding: utf-8 -*- # @Time : 2019/7/12 12:17 # @Author : AnWen import time from wsgiref.simple_server import make_server from showdata import showdata from jinja2 import Templatedef html():userinfo_data=showdata()with open('6jinja2和wsgiref動態框架.html', 'r', encoding='utf-8') as f:date = f.read()# print(date)tem=Template(date) ## 生成模板文件print(userinfo_data) #{'id': 1, 'name': 'anwen', 'age': 20}date=tem.render({'userinfo':userinfo_data})#模板的原理就是字符串替換,我們只要在HTML頁面中遵循jinja2的語法規則寫上,其內部就會按照指定的語法進行相應的替換,從而達到動態的返回內容。date = date.encode('utf-8')return date def css():with open('test.css', 'rb') as f:date = f.read()return date def js():with open('test.js', 'rb') as f:date = f.read()return date def ico():with open('wechat.ico', 'rb') as f:date = f.read()return date def jpg():with open('window.jpg', 'rb') as f:date = f.read()return dateurlpatterns = [('/', html),('/test.css', css),('/test.js', js),('/wechat.ico', ico),('/window.jpg', jpg) ]def application(environ, start_response):''':param environ: 是全部加工好的請求信息,加工成了一個字典,通過字典取值的方式就能拿到很多你想要拿到的信息:param start_response: 幫你封裝響應信息的(響應行和響應頭),注意下面的參數:return:'''# print(environ)## 設置HTTP響應的狀態碼和頭信息start_response('200 ok', [('k1', 'v1')])path = environ['PATH_INFO']for item in urlpatterns:if path == item[0]:ret = item[1]()breakelse:ret = '404 not found!'return [ret]httpd = make_server('127.0.0.1', 9000, application) print('Serving HTTP on port 9000...') httpd.serve_forever()

總結

以上是生活随笔為你收集整理的Django基础一之web框架的本质的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 玖玖爱av| 中文字幕在线亚洲 | 26uuu国产| 久久青青草原亚洲av无码麻豆 | 亚洲乱码精品久久久久.. | 麻豆国产一区 | 麻豆回家视频区一区二 | 青青操在线观看 | 日韩成人av电影 | 国产视频欧美视频 | 三级自拍视频 | 51福利视频| 男人干女人视频 | 中文字幕一区二区三区精品 | 久久久久麻豆v国产精华液好用吗 | 久久久久无码国产精品一区 | 亚洲精品日韩综合观看成人91 | 日本成人综合 | 成人在线免费小视频 | 中国字幕av| 猎艳山村丰满少妇 | 国产又粗又黄的视频 | 亚洲专区区免费 | 男人的天堂网在线 | 越南少妇做受xxx片 亚洲av综合色区无码一二三区 | 亚洲怡红院av | 亚州av成人 | 秋霞啪啪片 | 男人的天堂免费视频 | 精品人妻一区二区乱码 | 女生隐私免费看 | 久草一区 | 蜜乳av 懂色av 粉嫩av | 天堂在线观看视频 | 一区二区日韩视频 | 国产在线xxx| 三级黄视频| www插插插无码免费视频网站 | 91免费精品 | 日韩欧美亚洲一区二区三区 | 国产精品久久中文字幕 | 成人一区二区在线观看 | 9l视频自拍蝌蚪9l视频 | 亚洲 欧美 激情 小说 另类 | 国产欧美在线看 | 欧美成人精品一区 | 91美女免费看 | www.xxx国产| 国产高潮国产高潮久久久 | 中文字幕亚洲无线码在线一区 | 日韩女同互慰一区二区 | 综合精品久久 | 黄色小网站入口 | 精品无码一区二区三区爱欲 | a一级视频| 欧美日韩一二三四区 | 波多野结衣三级视频 | 国产女人18毛片水真多 | 狠狠干天天色 | 亚洲精品动漫在线观看 | 爱乃なみ加勒比在线播放 | 成人aaa| 久色资源| 久久久123 | 成人网在线播放 | 国产嫩草在线观看 | 欧美一区二区视频免费观看 | 伊人久综合 | 性色av一区二区三区四区 | 中文天堂网 | 亚洲天堂视频在线播放 | 99福利影院 | 亚洲国产精品第一页 | 国产成人在线播放视频 | 色偷偷在线观看 | 色老大网站 | 黄色免费网站观看 | 在线观看黄色动漫 | 国产乱子伦一区二区 | 日本亲与子乱ay中文 | 国产熟妇另类久久久久 | 亚洲性生活片 | 国产稀缺真实呦乱在线 | 免费成人电影在线观看 | 捆绑凌虐一区二区三区 | 国产欧美日本 | 激情 亚洲 | 国产午夜精品免费一区二区三区视频 | 人人干人人艹 | 7777久久亚洲中文字幕 | 在线亚洲不卡 | 日产精品久久久 | 天天躁日日躁狠狠躁欧美 | 欧美精品亚洲精品日韩精品 | 日本大尺度吃奶做爰久久久绯色 | 日韩熟女精品一区二区三区 | 视频在线观看99 | 国产经典三级 | 黄色精彩视频 |