讓我們一起聊聊 Django 框架
?Django是一個(gè)python開發(fā)者都比較熟悉的一個(gè)框架,這個(gè)屬于web方向的開發(fā)框架,而且Django是屬于大而全的,最出名的應(yīng)該屬于其全自動(dòng)化的管理后臺了,我們只需要使用ORM,做一些簡單的對象定義,就可以自動(dòng)生成對應(yīng)的數(shù)據(jù)庫的表結(jié)構(gòu),以及全功能的管理后臺。
Django框架的特點(diǎn)
功能較為完善,有著較高的開發(fā)效率,但是呢,性能擴(kuò)展比較有限,采用Django的項(xiàng)目,在流量達(dá)到一定的規(guī)模之后,需要對其進(jìn)行重構(gòu),才能夠滿足性能的要求,比較適合中小型的網(wǎng)站。
Django的設(shè)計(jì)哲學(xué)是徹底的將代碼合樣式進(jìn)行分離,Django從根本上杜絕在模板中進(jìn)行編碼處理數(shù)據(jù)的可能性。
Django先進(jìn)的APP設(shè)計(jì)理念,APP是可以插拔的,是不可多得的思想,不需要了,可以直接刪除,對系統(tǒng)整體影響不大。
這一點(diǎn)作為一個(gè)常年的Java開發(fā)者來說必須說一句,這個(gè)設(shè)計(jì)我認(rèn)為是和微服務(wù)思想中的Application是一個(gè)理念的,Java開發(fā)者最熟悉的莫過于spring全家桶,而spring全家桶大家也一定熟悉springboot,以及springcloud各種的服務(wù)治理。
我們開發(fā)的后端服務(wù),隨著業(yè)務(wù)的發(fā)展變得越來越臃腫的時(shí)候,也就需要拆分成多個(gè)服務(wù),而多個(gè)服務(wù)呢,做到了一個(gè)解耦合,互相調(diào)用,如果當(dāng)我們需要下掉一個(gè)服務(wù)的時(shí)候,也會變得相對來說比較簡單。
Django框架也存在一定的缺點(diǎn)。
Django包含了一些輕量級的不常用的功能模塊,這一點(diǎn)不如flask框架方便。
性能相對來說比較低,當(dāng)然這也不完全是框架的郭,也有一部分是python的問題,python本身就是屬于解釋性語言,其它的python框架也有同樣的問題。
WSGI協(xié)議 & uwsgi & wsgiref & Gunicorn
python web程序一般來說分為兩部分,服務(wù)器程序和應(yīng)用程序,服務(wù)器程序負(fù)責(zé)對socket服務(wù)器進(jìn)行封裝,并在客戶端請求服務(wù)端時(shí)將客戶端請求的各種數(shù)據(jù)和信息進(jìn)行整理。
應(yīng)用程序則負(fù)責(zé)具體的邏輯處理,為了方便應(yīng)用程序的開發(fā)就出現(xiàn)了很多的web框架,Django便是其中之一,服務(wù)器程序需要為不同的web框架提供不同的支持。
因此就需要一個(gè)標(biāo)準(zhǔn),只要服務(wù)器程序和應(yīng)用程序也就是web框架都支持這個(gè)標(biāo)準(zhǔn),服務(wù)器程序就可以web框架之間配合使用。
WSGI就是一種規(guī)范,它規(guī)定了使用python編寫的web應(yīng)用程序與web服務(wù)器程序之間的接口格式。
常見的符合WSGI協(xié)議的服務(wù)器程序有uwsgi,Gunicorn,而django框架自帶的服務(wù)器程序是wsgiref,當(dāng)django項(xiàng)目上線時(shí)可以更換成uwsgi或者Gunicorn。
Django的請求生命周期
圖片來源于網(wǎng)站,侵刪
1.瀏覽器發(fā)起請求。
2.WSGI創(chuàng)建socket服務(wù)器,接收請求HttpRequest,并將請求進(jìn)行初次封裝,然后將請求交給對應(yīng)的web框架Flask、Django。
3.中間件處理請求,幫助我們對請求進(jìn)行校驗(yàn)或者在請求對象中添加相關(guān)的數(shù)據(jù)。
4.URL路由,根據(jù)當(dāng)前請求的URL找到對應(yīng)的視圖函數(shù),映射。
5.view視圖,進(jìn)行業(yè)務(wù)處理,ORM處理數(shù)據(jù),從數(shù)據(jù)庫取出數(shù)據(jù)返回給view視圖,view視圖將數(shù)據(jù)渲染到對應(yīng)的template模板,并將數(shù)據(jù)返回。
6.中間件處理響應(yīng)。
7.WSGI返回相應(yīng)HttpResponse。
8.瀏覽器渲染。
列舉django中間件的5個(gè)方法?以及django中間件的應(yīng)用場景?
1.process_request:接收到客戶端信息后立即執(zhí)行,視圖函數(shù)之前。
2.process_response:返回到客戶端信息前最后執(zhí)行,視圖函數(shù)之后。
3.process_view:拿到視圖函數(shù)的名稱,參數(shù),執(zhí)行process_view()方法。
4.process_exception:視圖函數(shù)出錯(cuò)時(shí)執(zhí)行。
5.process_template_response:在視圖函數(shù)執(zhí)行完后立即執(zhí)行,前提是視圖返回的對象中有一個(gè)render()方法。
Django中的ORM中常用的獲取數(shù)據(jù)查詢集合的方法
常用方法包括filter和exclude方法。字符串模糊匹配可以使用icontains, in等多種方法。
qs1 = Article.objects.filter(title__icontains='django')
qs2 = Article.objects.filter(id__range=[1,9])
qs3 = Article.objects.filter(id__in=[1, 3, 6, 7, 9])
qs4 = Article.objects.filter(author=request.user).exclude(id=1)
Django中的QuerySet有哪些特性
Django的QuerySet主要有兩個(gè)特性:一是惰性的(lazy),二是自帶緩存。
article_list = Article.objects.filter(title__contains="django")
當(dāng)我們定義article_list的時(shí)候,Django的數(shù)據(jù)接口QuerySet并沒有對數(shù)據(jù)庫進(jìn)行任何查詢。無論你加多少過濾條件,Django都不會對數(shù)據(jù)庫進(jìn)行查詢。
只有當(dāng)你需要對article_list做進(jìn)一步運(yùn)算時(shí)(比如打印出查詢結(jié)果,判斷是否存在,統(tǒng)計(jì)查詢結(jié)果長度),Django才會真正執(zhí)行對數(shù)據(jù)庫的查詢(見下例1)。
這個(gè)過程被稱為queryset的執(zhí)行(evaluation)。
Django這樣設(shè)計(jì)的本意是盡量減少對數(shù)據(jù)庫的無效操作,比如查詢了結(jié)果而不用是計(jì)算資源的很大浪費(fèi)。
什么是基于函數(shù)的視圖(FBV)和基于類的視圖(CBV)以及各自的優(yōu)點(diǎn)
FBV(function base views) 就是在視圖里使用函數(shù)處理請求。CBV(class base views) 就是在視圖里使用類處理請求。
Python是一個(gè)面向?qū)ο蟮木幊陶Z言,如果只用函數(shù)來開發(fā),有很多面向?qū)ο蟮膬?yōu)點(diǎn)就錯(cuò)失了(繼承、封裝、多態(tài))。
所以Django在后來加入了Class-Based-View,可以讓我們用類寫View,這樣做的優(yōu)點(diǎn)主要下面兩種:
1.提高了代碼的復(fù)用性,可以使用面向?qū)ο蟮募夹g(shù),比如Mixin(多繼承)。
2.可以用不同的函數(shù)針對不同的HTTP方法處理,而不是通過很多if判斷,提高代碼可讀性。
你能列舉幾個(gè)減少數(shù)據(jù)庫查詢次數(shù)的方法嗎?
利用Django queryset的惰性和自帶緩存的特性。
使用select_related和prefetch_related方法在數(shù)據(jù)庫層面進(jìn)行Join操作。
使用緩存。
Django的模型繼承有哪幾種方式? 它們有什么區(qū)別以及何時(shí)使用它們?
Django的模型繼承有如下3種方式:
1. 抽象模型繼承(abstract model)。
2. 多表模型繼承(multi-table inheritance)。
3. 代理模型(proxy model)。
它們的區(qū)別如下:
Django不會為抽象模型在數(shù)據(jù)庫中生成自己的數(shù)據(jù)表。父類Meta中的abstract=True也不會傳遞給子類。
如果你發(fā)現(xiàn)多模型有很多共同字段時(shí),需使用抽象模型繼承。
多表模型繼承與抽象模型繼承最大的區(qū)別在于Django也會為父類模型建立自己的數(shù)據(jù)表,同時(shí)隱式地在父類和子類之間建立一個(gè)一對一關(guān)系。
如果我們只想改變某個(gè)模型的行為方法,而不是添加額外的字段或創(chuàng)建額外的數(shù)據(jù)表,我們就可以使用代理模型(proxy model)。設(shè)置一個(gè)代理模型,需要在子類模型Meta選項(xiàng)中設(shè)置proxy=True, Django不會為代理模型生成新的數(shù)據(jù)表。
django rest framework如何實(shí)現(xiàn)的用戶訪問頻率控制?
from rest_framework.throttling import SimpleRateThrottle。
這里使用的節(jié)流類是繼承了SimplePateThrottle類,而這個(gè)類利用了django內(nèi)置的緩存來存儲訪問記錄。
通過全局節(jié)流設(shè)置,所有的視圖類默認(rèn)是使用UserThrottle類進(jìn)行節(jié)流,如果不想使用默認(rèn)的類就自定義給throttle_classes屬性變量賦值,如:“throttle_classes = [VisitThrottle,]”。
Celery 分布式任務(wù)隊(duì)列
情景:用戶發(fā)起 request,并等待 response 返回。在本些 views 中,可能需要執(zhí)行一段耗時(shí)的程序,那么用戶就會等待很長時(shí)間,造成不好的用戶體驗(yàn),比如發(fā)送郵件、手機(jī)驗(yàn)證碼等。
使用 celery 后,情況就不一樣了。解決:將耗時(shí)的程序放到 celery 中執(zhí)行。
將多個(gè)耗時(shí)的任務(wù)添加到隊(duì)列 queue 中,也就是用 redis 實(shí)現(xiàn) broker 中間人,然后用多個(gè) worker 去監(jiān)聽隊(duì)列里的任務(wù)去執(zhí)行。
任務(wù) task:就是一個(gè) Python 函數(shù)。
隊(duì)列 queue:將需要執(zhí)行的任務(wù)加入到隊(duì)列中。
工人 worker:在一個(gè)新進(jìn)程中,負(fù)責(zé)執(zhí)行隊(duì)列中的任務(wù)。
代理人 broker:負(fù)責(zé)調(diào)度,在布置環(huán)境中使用 redis。?