Django:html
對於django,大而全的框架它的內部組件比較多,內部提供:ORM、Admin、中間件、Form、ModelForm、Session、緩存、信號、CSRF;功能也都挺完善的ajax
Flask :sql
flask,微型框架,內部組件就比較少了,可是有不少第三方組件來擴展它,好比說有那個wtform(與django的modelform相似,表單驗證)、flask-sqlalchemy(操做數據庫的)、flask-session、flask-migrate、flask-script、blinker可擴展強,第三方組件豐富。因此對他自己來講有那種短小精悍的感受數據庫
Tornado:django
是一個輕量級的Web框架,異步非阻塞+內置WebSocket功能。編程
'目標':經過一個線程處理N個併發請求(處理IO)。json
內部組件:
a.內部本身實現socket
b.路由系統
c.視圖
d.模板
e.cookie
f.csrfflask
共同點:後端
django和flask的共同點就是,他們2個框架都沒有寫socket,因此他們都是利用第三方模塊wsgi;而Tornado自帶socket組件。api
不一樣點:
可是內部使用的wsgi也是有些不一樣的:django自己運行起來使用wsgiref,而flask使用werkzeug wsgi,還有一個區別就是他們的請求管理不太同樣:django是經過將請求封裝成request對象,再經過參數傳遞,而flask是經過上下文管理機制
2. Django請求的生命週期?
用戶請求進來先走到 wsgi,而後將請求交給 django的中間件,穿過django中間件(方法是process_request),接着就是路由匹配,路由匹配成功以後就執行相應的視圖函數,在視圖函數中能夠調用orm作數據庫操做,再從模板路徑將模板拿到,而後在後臺進行模板渲染,模板渲染完成以後就變成一個字符串,再把這個字符串通過全部中間件(方法:process_response)和wsgi 返回給用戶
3.列舉Django的內置組件?
form組件:
- 對用戶請求的數據進行校驗
- 生成HTML標籤
PS:
- form對象是一個可迭代對象。
- 問題:choice的數據若是從數據庫獲取可能會形成數據沒法實時更新
- 重寫構造方法,在構造方法中從新去數據庫獲取值。
- ModelChoiceField字段
信號:
django的信號其實就是django內部爲開發者預留的一些自定製功能的鉤子。只要在某個信號中註冊了函數,那麼django內部執行的過程當中就會自動觸發註冊在信號中的函數。
場景:
在數據庫某些表中添加數據時,能夠進行日誌記錄。
CSRF(跨站點請求僞造):
目標:防止用戶直接向服務端發起POST請求。
它與XSS很是不一樣,XSS利用站點內的信任用戶,而CSRF則經過假裝來自受信任用戶的請求來利用受信任的網站。
對全部的post請求作驗證/ 將Django生成的一串字符串發送給客戶端,一種是從請求體發過來,一種是放在隱藏的標籤裏面用的是process_view
方案:先發送GET請求時,將token保存到:cookie、Form表單中(隱藏的input標籤),之後再發送請求時只要攜帶過來便可。
目前防護 CSRF 攻擊主要有三種策略:1).驗證 HTTP Referer 字段;2).在請求地址中添加 token 並驗證;3).在 HTTP 頭中自定義屬性並驗證
ContentType:
ContentType是django的一個組件(app),爲咱們找到django程序中全部app中的全部表並添加到記錄中。可使用它再加上表中的兩個字段實現:一張表和N張表建立FK(字段)關係。(簡單理解爲進行多表之間的關聯做用)
- 字段:表名稱
- 字段:數據行ID
應用:內部購買系統之表優惠券。
中間件:
對全部的請求進行批量處理,在視圖函數執行先後進行自定義操做。
應用:用戶登陸校驗
問題:爲甚麼不使用裝飾器?
若是不使用中間件,就須要給每一個視圖函數添加裝飾器,太繁瑣
認證組件:
只有認證經過的用戶才能訪問指定的url地址,好比:購買物品信息,須要登陸以後才能查看,沒有登陸,就不能查看,這時候須要用到認證組件
Auth模塊是Django自帶的用戶認證模塊
詳情:https://www.cnblogs.com/liuqingzheng/articles/9628105.html
權限組件:
用戶登陸後,將權限放到session中,每次請求進來都在中間件裏,根據當前的url去session中匹配,判斷當前用戶是否有權限訪問當前url,有權限就繼續訪問,沒有就返回,(檢查的東西就能夠放到中間件中進行統一處理)在process_request方法裏面作的,咱們的中間件是放在session後面,由於中間件須要到session裏面取數據
詳情:https://www.cnblogs.com/liuqingzheng/articles/9628105.html
session:
cookie與session區別:
(a)cookie是保存在瀏覽器端的鍵值對,而session是保存的服務器端的鍵值對,可是依賴cookie。(也能夠不依賴cookie,能夠放在url,或請求頭可是cookie比較方便)
(b)以登陸爲例,cookie爲經過登陸成功後,設置明文的鍵值對,並將鍵值對發送客戶端存,明文信息可能存在泄漏,不安全;session則是生成隨機字符串,發給用戶,並寫到瀏覽器的cookie中,同時服務器本身也會保存一份。
(c)在登陸驗證時,cookie:根據瀏覽器發送請求時附帶的cookie的鍵值對進行判斷,若是存在,則驗證經過;session:在請求用戶的cookie中獲取隨機字符串,根據隨機字符串在session中獲取其對應的值進行驗證
緩存:
經常使用的數據放在緩存裏面,就不用走視圖函數,請求進來經過全部的process_request,會到緩存裏面查數據,有就直接拿,沒有就走視圖函數
關鍵點:1:執行完全部的process_request纔去緩存取數據
2:執行完全部的process_response纔將數據放到緩存
關於緩存問題
1:爲何放在最後一個process_request纔去緩存
由於須要驗證完用戶的請求,才能返回數據
2:何時將數據放到緩存中
第一次走中間件,緩存沒有數據,會走視圖函數,從數據庫裏面取數據,
當走完process_response,纔將數據放到緩存裏,由於走process_response的時候可能給咱們的響應加處理
爲何使用緩存
將經常使用且不太頻繁修改的數據放入緩存。
之後用戶再來訪問,先去緩存查看是否存在,若是有就返回
不然,去數據庫中獲取並返回給用戶(再加入到緩存,以便下次訪問)
5.列舉Django中間件的5個方法?以及django中間件的應用場景?
process_request(self,request) 先走request 經過路由匹配返回
process_view(self, request, callback, callback_args,callback_kwargs)
(1)執行完全部中間件的request方法‘
(2)url匹配成功
(3)拿到 視圖函數的名稱、參數,(注意不執行) 再執行process_view()方法
(4)最後去執行視圖函數
process_template_response(self,request,response) 當視圖函數的返回值對象中有render方法時,該方法纔會被調用
process_exception(self, request, exception) 在視圖函數執行出錯時,返回錯誤信息
process_response(self, request, response)
6.FBV與CBV的區別
- 沒什麼區別,由於他們的本質都是函數。CBV的.as_view()返回的view函數,view函數中調用類的dispatch方法,在dispatch方法中經過反射執行get/post/delete/put等方法。
非要說區別的話:
- CBV比較簡潔,GET/POST等業務功能分別放在不一樣get/post函數中。FBV本身作判斷進行區分。
7.Django orm 中如何設置讀寫分離?
方式一:手動使用queryset的using方法
方式二:寫配置文件
8.基於Django使用ajax發送post請求時,均可以使用哪一種方法攜帶csrf token?
方式一:給每一個ajax都加上請求頭
方式二:須要先下載jQuery-cookie,才能去cookie中獲取token
方式三:搞個函數ajaxSetup,當有多的ajax請求,即會執行這個函數
9.Django中如何實現orm表中添加數據時建立一條日誌記錄。
給信號註冊函數:
使用django的信號機制,能夠在添加、刪除數據先後設置日誌記錄
pre_init # Django中的model對象執行其構造方法前,自動觸發
post_init # Django中的model對象執行其構造方法後,自動觸發
pre_save # Django中的model對象保存前,自動觸發
post_save # Django中的model對象保存後,自動觸發
pre_delete # Django中的model對象刪除前,自動觸發
post_delete # Django中的model對象刪除後,自動觸發
10.談談你對RESTful 規範的認識?
RESTful其實就是一套編寫接口的'協議',規定如何編寫以及如何設置返回值、狀態碼等信息。
# 最顯著的特色:
# 用restful:
給用戶一個url,根據method不一樣在後端作不一樣的處理
好比:post建立數據、get獲取數據、put和patch修改數據、delete刪除數據。
# 不用restful:
給調用者不少url,每一個url表明一個功能,好比:add_user/delte_user/edit_user/
# 固然,還有協議其餘的,好比:
'版本'來控制讓程序有多個版本共存的狀況,版本能夠放在 url、請求頭
(accept/自定義)、GET參數
'狀態碼'200/300/400/500
200 OK - [GET]:服務器成功返回用戶請求的數據,該操做是冪等的(Idempotent)。
400 INVALID REQUEST - [POST/PUT/PATCH]:用戶發出的請求有錯誤,服務器沒有進行新建或修改數據的操做,該操做是冪等的。
404 NOT FOUND - [*]:用戶發出的請求針對的是不存在的記錄,服務器沒有進行操做,該操做是冪等的。
500 INTERNAL SERVER ERROR - [*]:服務器發生錯誤,用戶將沒法判斷髮出的請求是否成功。
'url中儘可能使用名詞'restful也能夠稱爲「面向資源編程」
'api標示'
api.sex.com 儘可能將API部署在專用域名(會存在跨域問題)
www.sex.com/api/
11.什麼是RPC?
'遠程過程調用協議'是一種經過網絡從遠程計算機程序上請求服務,而不須要了解底層網絡技術的協議。
進化的順序: 先有的RPC,而後有的RESTful規範
12.爲何要使用django rest framework框架?
內部幫助咱們提供了不少方便的組件,咱們經過配置就能夠完成相應操
做,如:'序列化'能夠作用戶請求數據校驗+queryset對象的序列化稱爲json,'解析器'獲取用戶請求數據request.data,會自動根據content-type請求頭的不能對數據進行解析,'分頁'將從數據庫獲取到的數據在頁面進行分頁顯示。
還有其餘組件:'認證'、'權限'、'訪問頻率控制
Flask
1.Flask的優點?
Flask自由、靈活,可擴展性強,透明可控,第三方庫的選擇面廣,開發時能夠結合最流行最強大的Python庫。
2.Flask框架依賴組件有哪些?
依賴jinja2模板引擎
依賴werkzurg協議
3.Flask藍圖的做用
blueprint把實現不一樣功能的module分開.也就是把一個大的App分割成各自實現不一樣功能的module.
在一個blueprint中能夠調用另外一個blueprint的視圖函數, 但要加相應的blueprint名.
4.簡述Flask上下文管理流程?
# a、簡單來講,falsk上下文管理能夠分爲三個階段:
一、'請求進來時':將請求相關的數據放入上下文管理中
二、'在視圖函數中':要去上下文管理中取值
三、'請求響應':要將上下文管理中的數據清除
# b、詳細點來講:
一、'請求剛進來':
將request,session封裝在RequestContext類中app,g封裝在AppContext類中,並經過LocalStack將RequestContext和 AppContext放入Local類中
二、'視圖函數中':
經過localproxy--->偏函數--->localstack--->local取值
三、'請求響應時':
先執行save.session()再各自執行pop(),將local中的數據清除
5.Flask中的g的做用?
g是貫穿於一次請求的全局變量,當請求進來將g和current_app封裝爲一個AppContext類,再經過LocalStack將AppContext放入Local中,取值時經過偏函數在LocalStack、local中取值;響應時將local中的g數據刪除:
6.Flask執行流程?
7.什麼是偏函數?
簡單說functools.partial的做用就是,把一個函數的某些參數給固定住(也就是設置默認值),返回一個新的函數,調用這個新函數會更簡單
舉例:
#假設對int(x, base = 10),進行二次封裝#一般作法def to_int2(x): return int(x, base = 2)print(to_int2(‘101‘))#偏函數 作法import functoolsto_int2_partial = functools.partial(int, base = 2)print(to_int2_partial(‘101‘,base=2))#partial的函數聲明#def __init__(self, func, *args, **keywords):#由此處能夠看到其實就是作了#int(**keywords) ==>kw = {‘base‘ = 2} 然而‘101’會以*args的形式傳入到函數print(to_int2_partial(‘101‘,base=10))#result --> 101