面试之 Python 进阶
前端相關(guān)
1.談?wù)勀銓ttp協(xié)議的認(rèn)識。
瀏覽器本質(zhì),socket客戶端遵循Http協(xié)議
HTTP協(xié)議本質(zhì):通過\r\n分割的規(guī)范+ 請求響應(yīng)之后斷開鏈接 == > 無狀態(tài)、 短連接
具體:
Http協(xié)議是建立在tcp之上的,是一種規(guī)范,它規(guī)范定了發(fā)送的數(shù)據(jù)的數(shù)據(jù)格式,然而這個數(shù)據(jù)格式是通過\r\n 進(jìn)行分割的,請求頭與請求體也是通過2個\r\n分割的,響應(yīng)的時候,響應(yīng)頭與響應(yīng)體也是通過\r\n分割,并且還規(guī)定已請求已響應(yīng)就會斷開鏈接,即---> 短連接、無狀態(tài)
2.談?wù)勀銓ebsocket協(xié)議的認(rèn)識。
a.什么是websocket?
是給瀏覽器新建的一套協(xié)議
協(xié)議規(guī)定:創(chuàng)建連接后不斷開
通過'\r\n'分割,讓客戶端和服務(wù)端創(chuàng)建連接后不斷開、驗證+數(shù)據(jù)加密
# b.本質(zhì):
# 就是一個創(chuàng)建連接后不斷開的socket
# 當(dāng)連接成功后:
- 客戶端(瀏覽器)會自動向服務(wù)端發(fā)送消息
- 服務(wù)端接收后,會對該數(shù)據(jù)加密:base64(sha1(swk+magic_string))
- 構(gòu)造響應(yīng)頭
- 發(fā)送給客戶端
# 建立雙工通道,進(jìn)行收發(fā)數(shù)據(jù)
# c.框架中是如何使用websocket的?
django:channel
flask:gevent-websocket
tornado:內(nèi)置
# d.websocket的優(yōu)缺點
優(yōu)點:代碼簡單,不再重復(fù)創(chuàng)建連接
缺點:兼容性沒有長輪詢好,如IE會有不兼容
?WebSocket和HTTP的區(qū)別:
? http協(xié)議是用在應(yīng)用層的協(xié)議,他是基于tcp協(xié)議的,http協(xié)議建立鏈接也必須要有三次握手才能發(fā)送信息。
? http鏈接分為短鏈接,長鏈接,短鏈接是每次請求都要三次握手才能發(fā)送自己的信息。即每一個request對應(yīng)一個response。長鏈接是在一定的期限內(nèi)保持鏈接。保持TCP連接不斷開。客戶端與服務(wù)器通信,必須要有客戶端發(fā)起然后服務(wù)器返回結(jié)果。客戶端是主動的,服務(wù)器是被動的。?
? WebSocket他是為了解決客戶端發(fā)起多個http請求到服務(wù)器資源瀏覽器必須要經(jīng)過長時間的輪訓(xùn)問題而生的,他實現(xiàn)了多路復(fù)用,他是全雙工通信。在webSocket協(xié)議下客服端和瀏覽器可以同時發(fā)送信息。
? 建立了WenSocket之后服務(wù)器不必在瀏覽器發(fā)送request請求之后才能發(fā)送信息到瀏覽器。這時的服務(wù)器已有主動權(quán)想什么時候發(fā)就可以發(fā)送信息到服務(wù)器。而且信息當(dāng)中不必在帶有head的部分信息了與http的長鏈接通信來說,這種方式,不僅能降低服務(wù)器的壓力。而且信息當(dāng)中也減少了部分多余的信息。
3.什么是magic string ?
客戶端向服務(wù)端發(fā)送消息時,會有一個'sec-websocket-key'和'magic string'的隨機(jī)字符串(魔法字符串)
服務(wù)端接收到消息后會把他們連接成一個新的key串,進(jìn)行編碼、加密,確保信息的安全性
4.如何創(chuàng)建響應(yīng)式布局?
# a.可以通過引用Bootstrap實現(xiàn) # b.通過看Bootstrap源碼文件,可知其本質(zhì)就是通過CSS實現(xiàn)的<style>/*瀏覽器窗口寬度大于768,背景色變?yōu)?green*/@media (min-width: 768px) {.pg-header{background-color: green;}}/*瀏覽器窗口寬度大于992,背景色變?yōu)?pink*/@media (min-width: 992px) {.pg-header{background-color: pink;}}</style> </head> <body> <div class="pg-header"></div> </body>5.你曾經(jīng)使用過哪些前端框架?
jQuery
- BootStrap,H-ui
- Vue.js(與vue齊名的前端框架React和Angular)
6.什么是ajax請求?并使用jQuery和XMLHttpRequest對象實現(xiàn)一個ajax請求。
1.沒用ajax:瀏覽器訪問服務(wù)器請求,用戶看得到(頁面刷新也就等同于重新發(fā)請求,刷新看得到,也就等同于請求看得到)。等請求完,頁面刷新,新內(nèi)容出現(xiàn),用戶看到新內(nèi)容。
2.用ajax:瀏覽器訪問服務(wù)器請求,用戶看不到,是悄悄進(jìn)行。等請求完,頁面不刷新,新內(nèi)容也會出現(xiàn),用戶看到新內(nèi)容。
http://www.cnblogs.com/wupeiqi/articles/5703697.html
7.如何在前端實現(xiàn)輪訓(xùn)?
# 輪詢是在特定的的時間間隔(如每1秒),由瀏覽器對服務(wù)器發(fā)出HTTP request, # 然后由服務(wù)器返回最新的數(shù)據(jù)給客戶端的瀏覽器。 var xhr = new XMLHttpRequest();setInterval(function(){xhr.open('GET','/user');xhr.onreadystatechange = function(){};xhr.send();},1000)8.如何在前端實現(xiàn)長輪訓(xùn)?
# ajax實現(xiàn):在發(fā)送ajax后,服務(wù)器端會阻塞請求直到有數(shù)據(jù)傳遞或超時才返回。 # 客戶端JavaScript響應(yīng)處理函數(shù)會在處理完服務(wù)器返回的信息后,再次發(fā)出請求,重新建立連接。function ajax(){var xhr = new XMLHttpRequest();xhr.open('GET','/user');xhr.onreadystatechange = function(){ajax();};xhr.send();}9.vuex的作用?
1.不同組件之間共享狀態(tài),可以進(jìn)行狀態(tài)的修改和讀取。
2.可以理解為是一個全局對象,所有頁面都可以訪問
3.還有比較重要的單一狀態(tài)樹管理,讓數(shù)據(jù)的修改脈絡(luò)更加清晰,便于定位問題。
# 比如用戶做了一些加減的操作、三個頁面都要用、可以用傳參、但是很麻煩、這種時候用vuex就簡單一些
10.vue中的路由的攔截器的作用?
# 統(tǒng)一處理所有http請求和響應(yīng)時,可以用axios的攔截器。
# 通過配置http response inteceptor,當(dāng)后端接口返回401 Unauthorized(未授權(quán)),讓用戶重新登錄。
# so可以用來做登錄攔截驗證
11.axios的作用?
# axios是vue-resource后出現(xiàn)的Vue請求數(shù)據(jù)的插件
# 可以做的事情:
從瀏覽器中創(chuàng)建 XMLHttpRequest
從 node.js 發(fā)出 http 請求
支持 Promise API
攔截請求和響應(yīng)
轉(zhuǎn)換請求和響應(yīng)數(shù)據(jù)
取消請求
自動轉(zhuǎn)換JSON數(shù)據(jù)
客戶端支持防止 CSRF/XSRF
12.列舉vue的常見指令。
# 1、v-if指令:判斷指令,根據(jù)表達(dá)式值得真假來插入或刪除相應(yīng)的值。
# 2、v-show指令:
? # 條件渲染指令,無論返回的布爾值是true還是false,元素都會存在html中,
? # false的元素會隱藏在html中,并不會刪除.
# 3、v-else指令:配合v-if或v-else使用。
# 4、v-for指令:循環(huán)指令,相當(dāng)于遍歷。
# 5、v-bind:給DOM綁定元素屬性。
# 6、v-on指令:監(jiān)聽DOM事件。
13.簡述jsonp及實現(xiàn)原理?
應(yīng)為有同源策略,所以需要使用scripy 標(biāo)簽
# 原理:
1、先在客戶端注冊一個callback, 然后把callback的名字傳給服務(wù)器。
2、此時,服務(wù)器先生成 json 數(shù)據(jù)。
3、然后以 javascript 語法的方式,生成一個function , function 名字就是傳遞上來的參數(shù) jsonp.
4、最后將 json 數(shù)據(jù)直接以入?yún)⒌姆绞?#xff0c;放置到 function 中,這樣就生成了一段 js 語法的文檔,返回給客戶端。
客戶端瀏覽器,解析script標(biāo)簽,并執(zhí)行返回的 javascript 文檔,此時數(shù)據(jù)作為參數(shù),
傳入到了客戶端預(yù)先定義好的 callback 函數(shù)里.(動態(tài)執(zhí)行回調(diào)函數(shù))
# 注意
# JSON 是一種數(shù)據(jù)格式
# JSONP 是一種數(shù)據(jù)調(diào)用的方式
14.什么是cors ?
# 跨域資源共享(Cross-Origin Resource Sharing)
# 其本質(zhì)是設(shè)置響應(yīng)頭,使得瀏覽器允許跨域請求。
# 簡單請求(一次請求)
1、請求方式:HEAD、GET、POST
2、請求頭信息:
? ? Accept
? ? Accept-Language
? ? Content-Language
? ? Last-Event-ID
? ? Content-Type 對應(yīng)的值是以下三個中的任意一個
? ? ? ? ? ? ? ? ? ? ? ? ? ? application/x-www-form-urlencoded
? ? ? ? ? ? ? ? ? ? ? ? ? ? multipart/form-data
? ? ? ? ? ? ? ? ? ? ? ? ? ? text/plain
# 非簡單請求(兩次請求)
在發(fā)送真正的請求之前,會默認(rèn)發(fā)送一個'options'請求,做'預(yù)檢',預(yù)檢成功后才發(fā)送真正的請求
? ? # 預(yù)檢:
? ? 如果復(fù)雜請求是PUT等請求,則服務(wù)端需要設(shè)置允許某請求,否則“預(yù)檢”不通過
? ? ? ? Access-Control-Request-Method
? ? 如果復(fù)雜請求設(shè)置了請求頭,則服務(wù)端需要設(shè)置允許某請求頭,否則“預(yù)檢”不通過
? ? ? ? Access-Control-Request-Headers
15.列舉Http請求中常見的請求方式?
http請求方法有8種:
? ? ? ? 'GET'
? ? ? ? 'POST'
? ? ? ? 'HEAD'
? ? ? ? 'OPTIONS'
? ? ? ? 'PUT'(修改數(shù)據(jù))
? ? ? ? 'DELETE'
? ? ? ? 'TRACE'
? ? ? ? 'CONNECT'
16.列舉Http請求中的狀態(tài)碼?
# 2開頭(成功)
? ? 200:請求成功
? ? 202:已接受請求,尚未處理
? ? 204:請求成功,且不需返回內(nèi)容
# 3開頭(重定向)
? ? 301:永久重定向
? ? 302:臨時重定向
# 4開頭(客戶端錯誤)
? ? 400(Bad Request):請求的語義或是參數(shù)有錯
? ? 403(Forbidden):服務(wù)器拒絕了請求(csrf)
? ? 404(Not Found):找不到頁面(資源)
# 5開頭(服務(wù)器錯誤)
? ? 500:服務(wù)器遇到錯誤,無法完成請求
? ? 502:網(wǎng)關(guān)錯誤,一般是服務(wù)器壓力過大導(dǎo)致連接超時 ? ? ??
? ? 503:服務(wù)器宕機(jī)
17.列舉Http請求中常見的請求頭?
# 常見請求頭:User-Agent、Referer、Host、Cookie、Connection、Accept
18.看圖寫結(jié)果(js):
李杰
Python框架
19.django、flask、tornado框架的比較?
- django,大而全的框架它的內(nèi)部組件比較多,內(nèi)部提供:ORM、Admin、中間件、Form、ModelForm、Session、緩存、信號、CSRF;功能也都挺完善的
- flask,微型框架,內(nèi)部組件就比較少了,但是有很多第三方組件來擴(kuò)展它,比如說有那個wtform(與django的modelform類似,表單驗證)、flask-sqlalchemy(操作數(shù)據(jù)庫的)、flask-session、flask-migrate、flask-script、blinker可擴(kuò)展強(qiáng),第三方組件豐富。所以對他本身來說有那種短小精悍的感覺
- tornado,異步非阻塞。是一個輕量級的Web框架,異步非阻塞+內(nèi)置WebSocket功能。'目標(biāo)':通過一個線程處理N個并發(fā)請求(處理IO)。'內(nèi)部組件:內(nèi)部自己實現(xiàn)socket、路由系統(tǒng)、視圖、模板、cookie、csrf
django和flask的共同點就是,他們2個框架都沒有寫socket,所以他們都是利用第三方模塊wsgi。
但是內(nèi)部使用的wsgi也是有些不同的:django本身運(yùn)行起來使用wsgiref,而flask使用werkzeug wsgi
還有一個區(qū)別就是他們的請求管理不太一樣:django是通過將請求封裝成request對象,再通過參數(shù)傳遞,而flask是通過上下文管理機(jī)制
20.什么是wsgi?
是web服務(wù)網(wǎng)關(guān)接口,是一套協(xié)議。
是通過以下模塊實現(xiàn)了wsgi協(xié)議:
? ? - wsgiref
? ? - werkzurg
? ? - uwsgi ? 關(guān)于部署
以上模塊本質(zhì):編寫socket服務(wù)端,用于監(jiān)聽請求,當(dāng)有請求到來,則將請求數(shù)據(jù)進(jìn)行封裝,然后交給web框架處理。
Django?
21.django請求的生命周期?
用戶請求進(jìn)來先走到 wsgi --> 然后將請求交給 jango的中間件 --> 穿過django中間件(方法是process_request)接著就是 路由匹配 --> 路由匹配成功之后就執(zhí)行相應(yīng)的 視圖函數(shù) --> 在視圖函數(shù)中可以調(diào)用orm做數(shù)據(jù)庫操作?--> 再從模板路徑 將模板拿到 --> 然后在后臺進(jìn)行模板渲染 --> 模板渲染完成之后就變成一個字符串 --> 再把這個字符串經(jīng)過所有中間件(方法:process_response) 和wsgi 返回給用戶
22.列舉django的內(nèi)置組件?
form 組件 - 對用戶請求的數(shù)據(jù)進(jìn)行校驗 - 生成HTML標(biāo)簽 PS: - form對象是一個可迭代對象。 - 問題:choice的數(shù)據(jù)如果從數(shù)據(jù)庫獲取可能會造成數(shù)據(jù)無法實時更新- 重寫構(gòu)造方法,在構(gòu)造方法中重新去數(shù)據(jù)庫獲取值。- ModelChoiceField字段from django.forms import Formfrom django.forms import fieldsfrom django.forms.models import ModelChoiceFieldclass UserForm(Form):name = fields.CharField(label='用戶名',max_length=32)email = fields.EmailField(label='郵箱')ut_id = ModelChoiceField(queryset=models.UserType.objects.all()) 依賴:class UserType(models.Model):title = models.CharField(max_length=32)def __str__(self):return self.title信號 django的信號其實就是django內(nèi)部為開發(fā)者預(yù)留的一些自定制功能的鉤子。 只要在某個信號中注冊了函數(shù),那么django內(nèi)部執(zhí)行的過程中就會自動觸發(fā)注冊在信號中的函數(shù)。 如: pre_init # django的modal執(zhí)行其構(gòu)造方法前,自動觸發(fā) post_init # django的modal執(zhí)行其構(gòu)造方法后,自動觸發(fā) pre_save # django的modal對象保存前,自動觸發(fā) post_save # django的modal對象保存后,自動觸發(fā) 場景: 在數(shù)據(jù)庫某些表中添加數(shù)據(jù)時,可以進(jìn)行日志記錄。CSRF 目標(biāo):防止用戶直接向服務(wù)端發(fā)起POST請求。 對所有的post請求做驗證/ 將jango生成的一串字符串發(fā)送給我們,一種是從請求體發(fā)過來,一種是放在隱藏的標(biāo)簽里面用的是process_view 方案:先發(fā)送GET請求時,將token保存到:cookie、Form表單中(隱藏的input標(biāo)簽), 以后再發(fā)送請求時只要攜帶過來即可。ContentType contenttype是django的一個組件(app), 為我們找到django程序中所有app中的所有表并添加到記錄中。可以使用他再加上表中的兩個字段實現(xiàn):一張表和N張表創(chuàng)建FK關(guān)系。 - 字段:表名稱 - 字段:數(shù)據(jù)行ID 應(yīng)用:路飛表結(jié)構(gòu)優(yōu)惠券和專題課和學(xué)位課關(guān)聯(lián)。中間件 對所有的請求進(jìn)行批量處理,在視圖函數(shù)執(zhí)行前后進(jìn)行自定義操作。 應(yīng)用:用戶登錄校驗 問題:為甚么不使用裝飾器? 如果不使用中間件,就需要給每個視圖函數(shù)添加裝飾器,太繁瑣session cookie與session區(qū)別 (a)cookie是保存在瀏覽器端的鍵值對,而session是保存的服務(wù)器端的鍵值對,但是依賴cookie。(也可以不依賴cookie,可以放在url,或請求頭但是cookie比較方便) (b)以登錄為例,cookie為通過登錄成功后,設(shè)置明文的鍵值對,并將鍵值對發(fā)送客戶端存,明文信息可能存在泄漏,不安全;session則是生成隨機(jī)字符串,發(fā)給用戶,并寫到瀏覽器的cookie中,同時服務(wù)器自己也會保存一份。 (c)在登錄驗證時,cookie:根據(jù)瀏覽器發(fā)送請求時附帶的cookie的鍵值對進(jìn)行判斷,如果存在,則驗證通過;session:在請求用戶的cookie中獲取隨機(jī)字符串,根據(jù)隨機(jī)字符串在session中獲取其對應(yīng)的值進(jìn)行驗證cors跨域(場景:前后端分離時,本地測試開發(fā)時使用) 如果網(wǎng)站之間存在跨域,域名不同,端口不同會導(dǎo)致出現(xiàn)跨域,但凡出現(xiàn)跨域,瀏覽器就會出現(xiàn)同源策略的限制 解決:在我們的服務(wù)端給我們響應(yīng)數(shù)據(jù),加上響應(yīng)頭---> 在中間件加的緩存 常用的數(shù)據(jù)放在緩存里面,就不用走視圖函數(shù),請求進(jìn)來通過所有的process_request,會到緩存里面查數(shù)據(jù),有就直接拿,沒有就走視圖函數(shù)關(guān)鍵點:1:執(zhí)行完所有的process_request才去緩存取數(shù)據(jù)2:執(zhí)行完所有的process_response才將數(shù)據(jù)放到緩存關(guān)于緩存問題 1:為什么放在最后一個process_request才去緩存 因為需要驗證完用戶的請求,才能返回數(shù)據(jù)2:什么時候?qū)?shù)據(jù)放到緩存中 第一次走中間件,緩存沒有數(shù)據(jù),會走視圖函數(shù),取數(shù)據(jù)庫里面取數(shù)據(jù), 當(dāng)走完process_response,才將數(shù)據(jù)放到緩存里,因為,走process_response的時候可能給我們的響應(yīng)加處理3.為什么使用緩存 將常用且不太頻繁修改的數(shù)據(jù)放入緩存。 以后用戶再來訪問,先去緩存查看是否存在,如果有就返回 否則,去數(shù)據(jù)庫中獲取并返回給用戶(再加入到緩存,以便下次訪問)23.列舉django中間件的5個方法?以及django中間件的應(yīng)用場景?
process_request(self,request) ?先走request 通過路由匹配返回
process_view(self, request, callback, callback_args, callback_kwargs) 再返回執(zhí)行view
process_template_response(self,request,response) ? 當(dāng)視圖函數(shù)的返回值
process_exception(self, request, exception) ?當(dāng)視圖函數(shù)的返回值對象中有render方法時,該方法才會被調(diào)用
process_response(self, request, response)
24.簡述什么是FBV和CBV?
FBV 基于函數(shù) # FBV 寫法 # urls.pyurl(r'^login/$',views.login, name="login"),# views.py def login(request):if request.method == "POST":print(request.POST)return render(request,"login.html")# HTML <!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1"><title>登錄頁面</title> </head> <body> <form action="{% url 'login' %}" method="post" enctype="multipart/form-data"><input type="text" name="user2"><input type="file" name="file"><input type="submit" value="提交"></form> </body> </html>CBV 基于類 # urls.py url(r'^login/$',views.Login.as_view(), name="login"), # views.py from django.views import View class Login(View): # 類首字母大寫def get(self,request):return render(request,"login.html")def post(self,request):print(request.POST)return HttpResponse("OK")加裝飾器================================= class IndexView(View):# 如果是crsf相關(guān),必須放在此處def dispach(self,request):# 通過反射執(zhí)行post/get @method_decoretor(裝飾器函數(shù))def get(self,request):passdef post(self,request):pass 路由:IndexView.as_view()25.FBV與CBV的區(qū)別
- 沒什么區(qū)別,因為他們的本質(zhì)都是函數(shù)。CBV的.as_view()返回的view函數(shù),view函數(shù)中調(diào)用類的dispatch方法, 在dispatch方法中通過反射執(zhí)行g(shù)et/post/delete/put等方法。D非要說區(qū)別的話: - CBV比較簡潔,GET/POST等業(yè)務(wù)功能分別放在不同get/post函數(shù)中。FBV自己做判斷進(jìn)行區(qū)分。26.django的request對象是在什么時候創(chuàng)建的?
當(dāng)請求一個頁面時, Django會建立一個包含請求元數(shù)據(jù)的 HttpRequest 對象. 當(dāng)Django 加載對應(yīng)的視圖時, HttpRequest對象將作為視圖函數(shù)的第一個參數(shù). 每個視圖會返回一個HttpResponse對象.27.如何給CBV的程序添加裝飾器?
添加裝飾器 方式一: from django.views import View from django.utils.decorators import method_decorator ---> 需要引入memethod_decoratordef auth(func):def inner(*args,**kwargs):return func(*args,**kwargs)return innerclass UserView(View):@method_decorator(auth)def get(self,request,*args,**kwargs):return HttpResponse('...') 方式二: - csrf的裝飾器要加到dispath前面 from django.views import View from django.utils.decorators import method_decorator from django.views.decorators.csrf import csrf_exempt,csrf_protect ---> 需要引入 csrf_exemptclass UserView(View):@method_decorator(csrf_exempt)def dispatch(self, request, *args, **kwargs):return HttpResponse('...')或者: from django.views import View from django.utils.decorators import method_decorator from django.views.decorators.csrf import csrf_exempt,csrf_protect@method_decorator(csrf_exempt,name='dispatch') ---> 指定名字 class UserView(View):def dispatch(self, request, *args, **kwargs):return HttpResponse('...')28.列舉django orm 中所有的方法(QuerySet對象的所有方法)
返回QuerySet對象的方法有:all()filter()exclude()order_by()reverse()distinct()特殊的QuerySet:values() 返回一個可迭代的字典序列values_list() 返回一個可迭代的元組序列返回具體對象的:get()first()last()返回布爾值的方法有:exists()返回數(shù)字的方法有:count()?29.only和defer的區(qū)別?
def defer(self, *fields):models.UserInfo.objects.defer('username','id')或models.UserInfo.objects.filter(...).defer('username','id')#映射中排除某列數(shù)據(jù)def only(self, *fields):#僅取某個表中的數(shù)據(jù)models.UserInfo.objects.only('username','id')或models.UserInfo.objects.filter(...).only('username','id')30.select_related和prefetch_related的區(qū)別?
# 他倆都用于連表查詢,減少SQL查詢次數(shù) select_related主要針一對一和多對一關(guān)系進(jìn)行優(yōu)化,通過多表join關(guān)聯(lián)查詢,一次性獲得所有數(shù)據(jù), 存放在內(nèi)存中,但如果關(guān)聯(lián)的表太多,會嚴(yán)重影響數(shù)據(jù)庫性能。 def index(request):obj = Book.objects.all().select_related("publisher")return render(request, "index.html", locals())prefetch_related是通過分表,先獲取各個表的數(shù)據(jù),存放在內(nèi)存中,然后通過Python處理他們之間的關(guān)聯(lián)。 def index(request):obj = Book.objects.all().prefetch_related("publisher")return render(request, "index.html", locals())# 舉例 def select_related(self, *fields)# 性能相關(guān):表之間進(jìn)行join連表操作,一次性獲取關(guān)聯(lián)的數(shù)據(jù)。model.tb.objects.all().select_related()model.tb.objects.all().select_related('外鍵字段')model.tb.objects.all().select_related('外鍵字段__外鍵字段')def prefetch_related(self, *lookups)# 性能相關(guān):多表連表操作時速度會慢,使用其執(zhí)行多次SQL查詢在Python代碼中實現(xiàn)連表操作。# 獲取所有用戶表# 獲取用戶類型表where id in (用戶表中的查到的所有用戶ID)models.UserInfo.objects.prefetch_related('外鍵字段')from django.db.models import Count, Case, When, IntegerFieldArticle.objects.annotate(numviews=Count(Case(When(readership__what_time__lt=treshold, then=1), output_field=CharField(),)))students = Student.objects.all().annotate(num_excused_absences=models.Sum(models.Case(models.When(absence__type='Excused', then=1),default=0,output_field=models.IntegerField())))?
# 1次SQL # select * from userinfo objs = UserInfo.obejcts.all() for item in objs:print(item.name)# n+1次SQL # select * from userinfo objs = UserInfo.obejcts.all() for item in objs:# select * from usertype where id = item.id print(item.name,item.ut.title)# 1次SQL,使用select_related() # select * from userinfo inner join usertype on userinfo.ut_id = usertype.id objs = UserInfo.obejcts.all().select_related('ut') 連表查詢 for item in objs:print(item.name,item.ut.title).prefetch_related()# select * from userinfo where id <= 8# 計算:[1,2]# select * from usertype where id in [1,2]objs = UserInfo.obejcts.filter(id__lte=8).prefetch_related('ut')for obj in objs:print(obj.name,obj.ut.title)31.filter和exclude的區(qū)別?
def filter(self, *args, **kwargs)# 條件查詢(符合條件)# 查出符合條件# 條件可以是:參數(shù),字典,Qdef exclude(self, *args, **kwargs)# 條件查詢(排除條件)# 排除不想要的# 條件可以是:參數(shù),字典,Q32.列舉django orm中三種能寫sql語句的方法。
# 原生SQL ---> connection from django.db import connection, connections cursor = connection.cursor() # cursor = connections['default'].cursor() cursor.execute("""SELECT * from auth_user where id = %s""", [1]) row = cursor.fetchone() # fetchall()/fetchmany(..)# 靠近原生SQL-->extra\raw # extradef extra(self, select=None, where=None, params=None, tables=None, order_by=None, select_params=None)# 構(gòu)造額外的查詢條件或者映射,如:子查詢Entry.objects.extra(select={'new_id': "select col from sometable where othercol > %s"},select_params=(1,))Entry.objects.extra(where=['headline=%s'], params=['Lennon'])Entry.objects.extra(where=["foo='a' OR bar = 'a'", "baz = 'a'"])Entry.objects.extra(select={'new_id': "select id from tb where id > %s"}, s elect_params=(1,), order_by=['-nid'])# raw def raw(self, raw_query, params=None, translations=None, using=None):# 執(zhí)行原生SQLmodels.UserInfo.objects.raw('select * from userinfo')# 如果SQL是其他表時,必須將名字設(shè)置為當(dāng)前UserInfo對象的主鍵列名models.UserInfo.objects.raw('select id as nid,name as title from 其他表')# 為原生SQL設(shè)置參數(shù)models.UserInfo.objects.raw('select id as nid from userinfo where nid>%s', params=[12,])# 將獲取的到列名轉(zhuǎn)換為指定列名name_map = {'first': 'first_name', 'last': 'last_name', 'bd': 'birth_date', 'pk': 'id'}Person.objects.raw('SELECT * FROM some_other_table', translations=name_map)# 指定數(shù)據(jù)庫models.UserInfo.objects.raw('select * from userinfo', using="default")33.django orm 中如何設(shè)置讀寫分離?
# 方式一:手動使用queryset的using方法 from django.shortcuts import render,HttpResponse from app01 import models def index(request):models.UserType.objects.using('db1').create(title='普通用戶')# 手動指定去某個數(shù)據(jù)庫取數(shù)據(jù)result = models.UserType.objects.all().using('db1')print(result)return HttpResponse('...')# 方式二:寫配置文件 class Router1:# 指定到某個數(shù)據(jù)庫取數(shù)據(jù)def db_for_read(self, model, **hints):"""Attempts to read auth models go to auth_db."""if model._meta.model_name == 'usertype':return 'db1'else:return 'default'# 指定到某個數(shù)據(jù)庫存數(shù)據(jù)def db_for_write(self, model, **hints):"""Attempts to write auth models go to auth_db."""return 'default' # 再寫到配置 DATABASES = {'default': {'ENGINE': 'django.db.backends.sqlite3','NAME': os.path.join(BASE_DIR, 'db.sqlite3'),},'db1': {'ENGINE': 'django.db.backends.sqlite3','NAME': os.path.join(BASE_DIR, 'db.sqlite3'),} } DATABASE_ROUTERS = ['db_router.Router1',]34.F和Q的作用?
# F:主要用來獲取原數(shù)據(jù)進(jìn)行計算。 # Django 支持 F() 對象之間以及 F() 對象和常數(shù)之間的加減乘除和取模的操作。 # 修改操作也可以使用F函數(shù),比如將每件商品的價格都在原價格的基礎(chǔ)上增加10 from django.db.models import F from app01.models import GoodsGoods.objects.update(price=F("price")+10) # 對于goods表中每件商品的價格都在原價格的基礎(chǔ)上增加10元F查詢專門對對象中某列值的操作,不可使用__雙下劃線! Q:用來進(jìn)行復(fù)雜查詢Q查詢可以組合使用 “&”, “|” 操作符,當(dāng)一個操作符是用于兩個Q的對象,它產(chǎn)生一個新的Q對象,Q對象可以用 “~” 操作符放在前面表示否定,也可允許否定與不否定形式的組合。Q對象可以與關(guān)鍵字參數(shù)查詢一起使用,不過一定要把Q對象放在關(guān)鍵字參數(shù)查詢的前面。Q(條件1) | Q(條件2) 或Q(條件1) & Q(條件2) 且Q(條件1) & ~Q(條件2) 非35.values和values_list的區(qū)別?
def values(self, *fields):# 獲取每行數(shù)據(jù)為字典格式def values_list(self, *fields, **kwargs):# 獲取每行數(shù)據(jù)為元祖36.如何使用django orm批量創(chuàng)建數(shù)據(jù)?
def bulk_create(self, objs, batch_size=None):# 批量插入# batch_size表示一次插入的個數(shù)objs = [models.DDD(name='r11'),models.DDD(name='r22')]models.DDD.objects.bulk_create(objs, 10)37.django的 Form?和 ModeForm 的作用?
- 作用:- 對用戶請求數(shù)據(jù)格式進(jìn)行校驗- 自動生成HTML標(biāo)簽- 區(qū)別:- Form,字段需要自己手寫。class Form(Form):xx = fields.CharField(.)xx = fields.CharField(.)xx = fields.CharField(.)xx = fields.CharField(.)- ModelForm,可以通過Meta進(jìn)行定義class MForm(ModelForm):class Meta:fields = "__all__"model = UserInfo - 應(yīng)用:只要是客戶端向服務(wù)端發(fā)送表單數(shù)據(jù)時,都可以進(jìn)行使用,如:用戶登錄注冊38.django的Form組件中,如果字段中包含choices參數(shù),請使用兩種方式實現(xiàn)數(shù)據(jù)源實時更新。
# 方式一:重寫構(gòu)造方法,在構(gòu)造方法中重新去數(shù)據(jù)庫獲取值class UserForm(Form):name = fields.CharField(label='用戶名',max_length=32)email = fields.EmailField(label='郵箱')ut_id = fields.ChoiceField(# choices=[(1,'普通用戶'),(2,'IP用戶')]choices=[])def __init__(self,*args,**kwargs):super(UserForm,self).__init__(*args,**kwargs)self.fields['ut_id'].choices = models.UserType.objects.all().values_list('id','title')# 方式二: ModelChoiceField字段from django.forms import Formfrom django.forms import fieldsfrom django.forms.models import ModelChoiceFieldclass UserForm(Form):name = fields.CharField(label='用戶名',max_length=32)email = fields.EmailField(label='郵箱')ut_id = ModelChoiceField(queryset=models.UserType.objects.all()) # 依賴:class UserType(models.Model):title = models.CharField(max_length=32)def __str__(self):return self.title39.django的Model中的ForeignKey字段中的on_delete參數(shù)有什么作用?
在django2.0后,定義外鍵和一對一關(guān)系的時候需要加on_delete選項,此參數(shù)為了避免兩個表里的數(shù)據(jù)不一致問題,不然會報錯: TypeError: __init__() missing 1 required positional argument: 'on_delete'舉例說明:user=models.OneToOneField(User) owner=models.ForeignKey(UserProfile)需要改成: user=models.OneToOneField(User,on_delete=models.CASCADE) --在老版本這個參數(shù)(models.CASCADE)是默認(rèn)值 owner=models.ForeignKey(UserProfile,on_delete=models.CASCADE) --在老版本這個參數(shù)(models.CASCADE)是默認(rèn)值參數(shù)說明: on_delete有CASCADE、PROTECT、SET_NULL、SET_DEFAULT、SET()五個可選擇的值 CASCADE:此值設(shè)置,是級聯(lián)刪除。 PROTECT:此值設(shè)置,是會報完整性錯誤。 SET_NULL:此值設(shè)置,會把外鍵設(shè)置為null,前提是允許為null。 SET_DEFAULT:此值設(shè)置,會把設(shè)置為外鍵的默認(rèn)值。 SET():此值設(shè)置,會調(diào)用外面的值,可以是一個函數(shù)。 一般情況下使用CASCADE就可以了。40.django中csrf的實現(xiàn)機(jī)制?
目的:防止用戶直接向服務(wù)端發(fā)起POST請求- 用戶先發(fā)送GET獲取csrf token: Form表單中一個隱藏的標(biāo)簽 + token - 發(fā)起POST請求時,需要攜帶之前發(fā)送給用戶的csrf token; - 在中間件的process_view方法中進(jìn)行校驗。在html中添加{%csrf_token%}標(biāo)簽41.django如何實現(xiàn)websocket?
django中可以通過channel實現(xiàn)websocket42.基于django使用ajax發(fā)送post請求時,都可以使用哪種方法攜帶csrf token?
# 方式一給每個ajax都加上上請求頭function Do1(){$.ajax({url:"/index/",data:{id:1},type:'POST',data:{csrfmiddlewaretoken:'{{ csrf_token }}',name:'alex'}success:function(data){console.log(data);}});}# 方式二:需要先下載jQuery-cookie,才能去cookie中獲取tokenfunction Do1(){$.ajax({url:"/index/",data:{id:1},type:'POST',headers:{'X-CSRFToken':$.cookie('csrftoken') // 去cookie中獲取},success:function(data){console.log(data);}});}方式三:搞個函數(shù)ajaxSetup,當(dāng)有多的ajax請求,即會執(zhí)行這個函數(shù)$.ajaxSetup({beforeSend:function (xhr,settings) {xhr.setRequestHeader("X-CSRFToken",$.cookie('csrftoken'))} });函數(shù)版本 <body> <input type="button" onclick="Do1();" value="Do it"/> <input type="button" onclick="Do2();" value="Do it"/> <input type="button" onclick="Do3();" value="Do it"/><script src="/static/jquery-3.3.1.min.js"></script> <script src="/static/jquery.cookie.js"></script> <script>$.ajaxSetup({beforeSend: function(xhr, settings) {xhr.setRequestHeader("X-CSRFToken", $.cookie('csrftoken'));}});function Do1(){$.ajax({url:"/index/",data:{id:1},type:'POST',success:function(data){console.log(data);}});}function Do2(){$.ajax({url:"/index/",data:{id:1},type:'POST',success:function(data){console.log(data);}});}function Do3(){$.ajax({url:"/index/",data:{id:1},type:'POST',success:function(data){console.log(data);}});} </script> </body>43.django中如何實現(xiàn)orm表中添加數(shù)據(jù)時創(chuàng)建一條日志記錄。
?給信號注冊函數(shù)
使用django的信號機(jī)制,可以在添加、刪除數(shù)據(jù)前后設(shè)置日志記錄
pre_init ?# Django中的model對象執(zhí)行其構(gòu)造方法前,自動觸發(fā)
post_init ?# Django中的model對象執(zhí)行其構(gòu)造方法后,自動觸發(fā)
pre_save ?# Django中的model對象保存前,自動觸發(fā)
post_save ?# Django中的model對象保存后,自動觸發(fā)
pre_delete ?# Django中的model對象刪除前,自動觸發(fā)
post_delete ?# Django中的model對象刪除后,自動觸發(fā)
44.django緩存如何設(shè)置?
jango中提供了6種緩存方式:開發(fā)調(diào)試(不加緩存)內(nèi)存文件數(shù)據(jù)庫Memcache緩存(python-memcached模塊)Memcache緩存(pylibmc模塊)安裝第三方組件支持redis:django-redis組件設(shè)置緩存 # 全站緩存(中間件) MIDDLEWARE_CLASSES = (‘django.middleware.cache.UpdateCacheMiddleware’, #第一'django.middleware.common.CommonMiddleware',‘django.middleware.cache.FetchFromCacheMiddleware’, #最后 )# 視圖緩存 from django.views.decorators.cache import cache_page import time@cache_page(15) #超時時間為15秒 def index(request):t=time.time() #獲取當(dāng)前時間return render(request,"index.html",locals())# 模板緩存 {% load cache %}<h3 style="color: green">不緩存:-----{{ t }}</h3>{% cache 2 'name' %} # 存的key<h3>緩存:-----:{{ t }}</h3> {% endcache %}45.django的緩存能使用redis嗎?如果可以的話,如何配置?
pip install django-redis apt-get install redis-serv# 在setting添加配置文件 CACHES = {"default": {"BACKEND": "django_redis.cache.RedisCache", # 緩存類型"LOCATION": "127.0.0.1:6379", # ip端口"OPTIONS": {"CLIENT_CLASS": "django_redis.client.DefaultClient", #"CONNECTION_POOL_KWARGS": {"max_connections": 100} # 連接池最大連接數(shù)# "PASSWORD": "密碼",}} }# 使用 from django.shortcuts import render,HttpResponse from django_redis import get_redis_connectiondef index(request): # 根據(jù)名字去連接池中獲取連接 conn = get_redis_connection("default")conn.hset('n1','k1','v1') # 存數(shù)據(jù)return HttpResponse('...')46.django路由系統(tǒng)中name的作用?
路由系統(tǒng)中name的作用:反向解析路由字符串
url(r'^home', views.home, name='home')
在模板中使用:{?%?url?'home'?%}
在視圖中使用:reverse(“home”)
47.django的模板中filter和simple_tag的區(qū)別?
filter : 類似管道,只能接受兩個參數(shù)第一個參數(shù)是|前的數(shù)據(jù)
simple_tag : 類似函數(shù)
1、模板繼承:{?%?extends?'layouts.html'?%}
2、自定義方法
????'filter':只能傳遞兩個參數(shù),可以在if、for語句中使用
????'simple_tag':可以無線傳參,不能在if for中使用
????'inclusion_tags':可以使用模板和后端數(shù)據(jù)
3、防xss攻擊:?'|safe'、'mark_safe'
48.django-debug-toolbar的作用?
一、查看訪問的速度、數(shù)據(jù)庫的行為、cache命中等信息。?
二、尤其在Mysql訪問等的分析上大有用處(sql查詢速度)
49.django中如何實現(xiàn)單元測試?
對于每一個測試方法都會將setUp()和tearDown()方法執(zhí)行一遍
會單獨新建一個測試數(shù)據(jù)庫來進(jìn)行數(shù)據(jù)庫的操作方面的測試,默認(rèn)在測試完成后銷毀。
在測試方法中對數(shù)據(jù)庫進(jìn)行增刪操作,最后都會被清除。也就是說,在test_add中插入的數(shù)據(jù),在test_add測試結(jié)束后插入的數(shù)據(jù)會被清除。
django單元測試時為了模擬生產(chǎn)環(huán)境,會修改settings中的變量,例如, 把DEBUG變量修改為True, 把ALLOWED_HOSTS修改為[*]。
50.解釋orm中 db first 和 code first的含義?
db first: 先創(chuàng)建數(shù)據(jù)庫,再更新表模型
code first:先寫表模型,再更新數(shù)據(jù)庫
https://www.cnblogs.com/jassin-du/p/8988897.html
51.django中如何根據(jù)數(shù)據(jù)庫表生成model中的類?
1、修改seting文件,在setting里面設(shè)置要連接的數(shù)據(jù)庫類型和名稱、地址
2、運(yùn)行下面代碼可以自動生成models模型文件
? ? ? ?- python manage.py inspectdb
3、創(chuàng)建一個app執(zhí)行下下面代碼:
? ? ? ?- python manage.py inspectdb > app/models.py?
52.使用orm和原生sql的優(yōu)缺點?
SQL:
# 優(yōu)點:執(zhí)行速度快
# 缺點:編寫復(fù)雜,開發(fā)效率不高
ORM:
# 優(yōu)點:讓用戶不再寫SQL語句,提高開發(fā)效率;可以很方便地引入數(shù)據(jù)緩存之類的附加功能
# 缺點:在處理多表聯(lián)查、where條件復(fù)雜查詢時,ORM的語法會變得復(fù)雜;沒有原生SQL速度快
53.簡述MVC和MTV
MVC:model(數(shù)據(jù)庫)、view(模塊)、controller(視圖,控制)
MTV:model(數(shù)據(jù)庫)、tempalte(視圖)、view(控制)?
54.django的contenttype組件的作用?
contenttype是django的一個組件(app),它可以將django下所有app下的表記錄下來
可以使用他再加上表中的兩個字段,實現(xiàn)一張表和N張表動態(tài)創(chuàng)建FK關(guān)系。
? ?- 字段:表名稱
? ?- 字段:數(shù)據(jù)行ID
應(yīng)用:路飛表結(jié)構(gòu)優(yōu)惠券和專題課和學(xué)位課關(guān)聯(lián)
Restfull
55.談?wù)勀銓estfull 規(guī)范的認(rèn)識?
restful其實就是一套編寫接口的'協(xié)議',規(guī)定如何編寫以及如何設(shè)置返回值、狀態(tài)碼等信息。
# 最顯著的特點:
# 用restful:?
? ? 給用戶一個url,根據(jù)method不同在后端做不同的處理
? ? 比如:post創(chuàng)建數(shù)據(jù)、get獲取數(shù)據(jù)、put和patch修改數(shù)據(jù)、delete刪除數(shù)據(jù)。
# 不用restful:?
? ? 給調(diào)用者很多url,每個url代表一個功能,比如:add_user/delte_user/edit_user/
# 當(dāng)然,還有協(xié)議其他的,比如:
? ? '版本'來控制讓程序有多個版本共存的情況,版本可以放在 url、請求頭(accept/自定義)、GET參數(shù)
? ? '狀態(tài)碼'200/300/400/500
? ? 'url中盡量使用名詞'restful也可以稱為“面向資源編程”
? ? 'api標(biāo)示'
? ? ? ? api.luffycity.com
? ? ? ? www.luffycity.com/api/
56.接口的冪等性是什么意思?
'一個接口通過1次相同的訪問,再對該接口進(jìn)行N次相同的訪問時,對資源不造影響就認(rèn)為接口具有冪等性。'GET, #第一次獲取結(jié)果、第二次也是獲取結(jié)果對資源都不會造成影響,冪等。POST, #第一次新增數(shù)據(jù),第二次也會再次新增,非冪等。PUT, #第一次更新數(shù)據(jù),第二次不會再次更新,冪等。PATCH,#第一次更新數(shù)據(jù),第二次不會再次更新,非冪等。DELTE,#第一次刪除數(shù)據(jù),第二次不在再刪除,冪等。57.什么是RPC?
'遠(yuǎn)程過程調(diào)用協(xié)議' 是一種通過網(wǎng)絡(luò)從遠(yuǎn)程計算機(jī)程序上請求服務(wù),而不需要了解底層網(wǎng)絡(luò)技術(shù)的協(xié)議。 進(jìn)化的順序: 現(xiàn)有的RPC,然后有的RESTful規(guī)范58.Http和Https的區(qū)別?
#Http: 80端口 #https: 443端口 # http信息是明文傳輸,https則是具有安全性的ssl加密傳輸協(xié)議。 #- 自定義證書 - 服務(wù)端:創(chuàng)建一對證書- 客戶端:必須攜帶證書 #- 購買證書- 服務(wù)端: 創(chuàng)建一對證書,。。。。- 客戶端: 去機(jī)構(gòu)獲取證書,數(shù)據(jù)加密后發(fā)給咱們的服務(wù)單- 證書機(jī)構(gòu):公鑰給改機(jī)構(gòu)59.為什么要使用django rest framework框架?
# 在編寫接口時可以不使用django rest framework框架, # 不使用:也可以做,可以用django的CBV來實現(xiàn),開發(fā)者編寫的代碼會更多一些。 # 使用:內(nèi)部幫助我們提供了很多方便的組件,我們通過配置就可以完成相應(yīng)操作,如:'序列化'可以做用戶請求數(shù)據(jù)校驗+queryset對象的序列化稱為json'解析器'獲取用戶請求數(shù)據(jù)request.data,會自動根據(jù)content-type請求頭的不能對數(shù)據(jù)進(jìn)行解析'分頁'將從數(shù)據(jù)庫獲取到的數(shù)據(jù)在頁面進(jìn)行分頁顯示。# 還有其他組件:'認(rèn)證'、'權(quán)限'、'訪問頻率控制?60.django rest framework框架中都有那些組件?
#- 路由,自動幫助開發(fā)者快速為一個視圖創(chuàng)建4個urlwww.oldboyedu.com/api/v1/student/$www.oldboyedu.com/api/v1/student(?P<format>\w+)$www.oldboyedu.com/api/v1/student/(?P<pk>\d+)/$www.oldboyedu.com/api/v1/student/(?P<pk>\d+)(?P<format>\w+)$ #- 版本處理- 問題:版本都可以放在那里?- url- GET - 請求頭 #- 認(rèn)證 - 問題:認(rèn)證流程? #- 權(quán)限 - 權(quán)限是否可以放在中間件中?以及為什么? #- 訪問頻率的控制匿名用戶可以真正的防止?無法做到真正的訪問頻率控制,只能把小白拒之門外。如果要封IP,使用防火墻來做。登錄用戶可以通過用戶名作為唯一標(biāo)示進(jìn)行控制,如果有人注冊很多賬號,則無法防止。 #- 視圖 #- 解析器 ,根據(jù)Content-Type請求頭對請求體中的數(shù)據(jù)格式進(jìn)行處理。request.data #- 分頁 #- 序列化- 序列化- source- 定義方法- 請求數(shù)據(jù)格式校驗 #- 渲染器?61.django rest framework框架中的視圖都可以繼承哪些類
a. 繼承APIView(最原始)但定制性比較強(qiáng)這個類屬于rest framework中的頂層類,內(nèi)部幫助我們實現(xiàn)了只是基本功能:認(rèn)證、權(quán)限、頻率控制,但凡是數(shù)據(jù)庫、分頁等操作都需要手動去完成,比較原始。class GenericAPIView(APIView)def post(...):pass b.繼承GenericViewSet(ViewSetMixin,generics.GenericAPIView)首先他的路由就發(fā)生變化如果繼承它之后,路由中的as_view需要填寫對應(yīng)關(guān)系在內(nèi)部也幫助我們提供了一些方便的方法:get_querysetget_objectget_serializerget_serializer_classget_serializer_contextfilter_queryset 注意:要設(shè)置queryset字段,否則會拋出斷言的異常。代碼 只提供增加功能 只繼承GenericViewSetclass TestView(GenericViewSet):serialazer_class = xxxdef creat(self,*args,**kwargs):pass # 獲取數(shù)據(jù)并對數(shù)據(jù)c. 繼承 modelviewset --> 快速快發(fā)-ModelViewSet(增刪改查全有+數(shù)據(jù)庫操作)-mixins.CreateModelMixin(只有增),GenericViewSet-mixins.CreateModelMixin,DestroyModelMixin,GenericViewSet對數(shù)據(jù)庫和分頁等操作不用我們在編寫,只需要繼承相關(guān)類即可。示例:只提供增加功能 class TestView(mixins.CreateModelMixin,GenericViewSet):serializer_class = XXXXXXX *** modelviewset --> 快速開發(fā),復(fù)雜點的genericview、apiview62.簡述 django rest framework框架的認(rèn)證流程。
- 如何編寫?寫類并實現(xiàn)authenticators請求進(jìn)來認(rèn)證需要編寫一個類,類里面有一個authenticators方法,我們可以自定義這個方法,可以定制3類返回值。成功返回元組,返回none為匿名用戶,拋出異常為認(rèn)證失敗。源碼流程:請求進(jìn)來先走dispatch方法,然后封裝的request對象會執(zhí)行user方法,由user觸發(fā)authenticators認(rèn)證流程 - 方法中可以定義三種返回值:- (user,auth),認(rèn)證成功- None , 匿名用戶- 異常 ,認(rèn)證失敗 - 流程:- dispatch - 再去request中進(jìn)行認(rèn)證處理63.django rest framework如何實現(xiàn)的用戶訪問頻率控制??
# 對匿名用戶,根據(jù)用戶IP或代理IP作為標(biāo)識進(jìn)行記錄,為每個用戶在redis中建一個列表{throttle_1.1.1.1:[1526868876.497521,152686885.497521...],throttle_1.1.1.2:[1526868876.497521,152686885.497521...],throttle_1.1.1.3:[1526868876.497521,152686885.497521...],} 每個用戶再來訪問時,需先去記錄中剔除過期記錄,再根據(jù)列表的長度判斷是否可以繼續(xù)訪問。'如何封IP':在防火墻中進(jìn)行設(shè)置 -------------------------------------------------------------------------- # 對注冊用戶,根據(jù)用戶名或郵箱進(jìn)行判斷。{throttle_xxxx1:[1526868876.497521,152686885.497521...],throttle_xxxx2:[1526868876.497521,152686885.497521...],throttle_xxxx3:[1526868876.497521,152686885.497521...],} 每個用戶再來訪問時,需先去記錄中剔除過期記錄,再根據(jù)列表的長度判斷是否可以繼續(xù)訪問。 \如1分鐘:40次,列表長度限制在40,超過40則不可訪問Flask
64.Flask框架的優(yōu)勢?
Flask自由、靈活,可擴(kuò)展性強(qiáng),透明可控,第三方庫的選擇面廣,開發(fā)時可以結(jié)合最流行最強(qiáng)大的Python庫,
65.Flask框架依賴組件
# 依賴jinja2模板引擎
# 依賴werkzurg協(xié)議
66.Flask藍(lán)圖的作用
# blueprint把實現(xiàn)不同功能的module分開.也就是把一個大的App分割成各自實現(xiàn)不同功能的module.
# 在一個blueprint中可以調(diào)用另一個blueprint的視圖函數(shù), 但要加相應(yīng)的blueprint名.
67.列舉使用的Flask第三方組件?
# Flask組件
? ? flask-session ?session放在redis
? ? flask-SQLAlchemy 如django里的ORM操作
? ? flask-migrate ?數(shù)據(jù)庫遷移
? ? flask-script ?自定義命令
? ? blinker ?信號-觸發(fā)信號
# 第三方組件
? ? Wtforms 快速創(chuàng)建前端標(biāo)簽、文本校驗
? ? dbutile ? ? 創(chuàng)建數(shù)據(jù)庫連接池
? ? gevnet-websocket 實現(xiàn)websocket
# 自定義Flask組件
? ? 自定義auth認(rèn)證?
? ? 參考flask-login組件
68.簡述Flask上下文管理流程?
# a、簡單來說,falsk上下文管理可以分為三個階段:
1、'請求進(jìn)來時':將請求相關(guān)的數(shù)據(jù)放入上下文管理中
2、'在視圖函數(shù)中':要去上下文管理中取值
3、'請求響應(yīng)':要將上下文管理中的數(shù)據(jù)清除
# b、詳細(xì)點來說:
1、'請求剛進(jìn)來':
????????將request,session封裝在RequestContext類中
????????app,g封裝在AppContext類中
????????并通過LocalStack將requestcontext和appcontext放入Local類中
2、'視圖函數(shù)中':
????????通過localproxy--->偏函數(shù)--->localstack--->local取值
3、'請求響應(yīng)時':
????????先執(zhí)行save.session()再各自執(zhí)行pop(),將local中的數(shù)據(jù)清除
69.Flask中的g的作用?
# g是貫穿于一次請求的全局變量,當(dāng)請求進(jìn)來將g和current_app封裝為一個APPContext類,
# 再通過LocalStack將Appcontext放入Local中,取值時通過偏函數(shù)在LocalStack、local中取值;
# 響應(yīng)時將local中的g數(shù)據(jù)刪除:
Flask中上下文管理主要涉及到了那些相關(guān)的類?并描述類主要作用?
RequestContext ?#封裝進(jìn)來的請求(賦值給ctx)
AppContext? ? ? ? ?#封裝app_ctx
LocalStack? ? ? ? ? #將local對象中的數(shù)據(jù)維護(hù)成一個棧(先進(jìn)后出)
Local? ? ? ? ? ? ? ? ? ?#保存請求上下文對象和app上下文對象
為什么要Flask把Local對象中的的值stack 維護(hù)成一個列表?
# 因為通過維護(hù)成列表,可以實現(xiàn)一個棧的數(shù)據(jù)結(jié)構(gòu),進(jìn)棧出棧時只取一個數(shù)據(jù),巧妙的簡化了問題。
# 還有,在多app應(yīng)用時,可以實現(xiàn)數(shù)據(jù)隔離;列表里不會加數(shù)據(jù),而是會生成一個新的列表
# local是一個字典,字典里key(stack)是唯一標(biāo)識,value是一個列表
Flask中多app應(yīng)用是怎么完成?
請求進(jìn)來時,可以根據(jù)URL的不同,交給不同的APP處理。藍(lán)圖也可以實現(xiàn)。
????#app1 = Flask('app01')
????#app2 = Flask('app02')
????#@app1.route('/index')
????#@app2.route('/index2')
源碼中在DispatcherMiddleware類里調(diào)用app2.__call__,
? 原理其實就是URL分割,然后將請求分發(fā)給指定的app。
之后app也按單app的流程走。就是從app.__call__走。
在Flask中實現(xiàn)WebSocket需要什么組件?
?gevent-websocket
wtforms組件的作用?
#快速創(chuàng)建前端標(biāo)簽、文本校驗;如django的ModelForm
Flask框架默認(rèn)session處理機(jī)制?
# 前提:
? ? 不熟的話:記不太清了,應(yīng)該是……分兩個階段吧 ??
# 創(chuàng)建:
? ? 當(dāng)請求剛進(jìn)來的時候,會將request和session封裝成一個RequestContext()對象,
? ? 接下來把這個對象通過LocalStack()放入內(nèi)部的一個Local()對象中;
?因為剛開始 Local 的ctx中session是空的;
?所以,接著執(zhí)行open_session,將cookie 里面的值拿過來,重新賦值到ctx中
? ? (Local實現(xiàn)對數(shù)據(jù)隔離,類似threading.local)?
# 銷毀:
? ? 最后返回時執(zhí)行 save_session() 將ctx 中的session讀出來進(jìn)行序列化,寫到cookie
? ? 然后給用戶,接著把 ctx pop掉
解釋Flask框架中的Local對象和threading.local對象的區(qū)別?
# a.threading.local
作用:為每個線程開辟一塊空間進(jìn)行數(shù)據(jù)存儲(數(shù)據(jù)隔離)。
問題:自己通過字典創(chuàng)建一個類似于threading.local的東西。
storage = {
? ?4740: {val: 0},
? ?4732: {val: 1},
? ?4731: {val: 3},
? ?}
# b.自定義Local對象
作用:為每個線程(協(xié)程)開辟一塊空間進(jìn)行數(shù)據(jù)存儲(數(shù)據(jù)隔離)。
class Local(object):
? ?def __init__(self):
? ? ? object.__setattr__(self, 'storage', {})
? ?def __setattr__(self, k, v):
? ? ? ident = get_ident()
? ? ? if ident in self.storage:
? ? ? ? ?self.storage[ident][k] = v
? ? ? else:
? ? ? ? ?self.storage[ident] = {k: v}
? ?def __getattr__(self, k):
? ? ? ident = get_ident()
? ? ? return self.storage[ident][k]
obj = Local()
def task(arg):
? ?obj.val = arg
? ?obj.xxx = arg
? ?print(obj.val)
for i in range(10):
? ?t = Thread(target=task, args=(i,))
? ?t.start()
Flask中 blinker 是什么?
# flask中的信號blinker
信號主要是讓開發(fā)者可是在flask請求過程中定制一些行為。
或者說flask在列表里面預(yù)留了幾個空列表,在里面存東西。
簡言之,信號允許某個'發(fā)送者'通知'接收者'有事情發(fā)生了
@ before_request有返回值,blinker沒有返回值
# 10個信號
request_started = _signals.signal('request-started') #請求到來前執(zhí)行
request_finished = _signals.signal('request-finished') #請求結(jié)束后執(zhí)行
before_render_template = _signals.signal('before-render-template')#模板渲染前執(zhí)行
template_rendered = _signals.signal('template-rendered')#模板渲染后執(zhí)行
got_request_exception = _signals.signal('got-request-exception') #請求執(zhí)行出現(xiàn)異常時執(zhí)行
request_tearing_down = _signals.signal('request-tearing-down')#請求執(zhí)行完畢后自動執(zhí)行(無論成功與否)
appcontext_tearing_down = _signals.signal('appcontext-tearing-down')# 請求上下文執(zhí)行完畢后自動執(zhí)行(無論成功與否)
appcontext_pushed = _signals.signal('appcontext-pushed') #請求app上下文push時執(zhí)行
appcontext_popped = _signals.signal('appcontext-popped') #請求上下文pop時執(zhí)行
message_flashed = _signals.signal('message-flashed')#調(diào)用flask在其中添加數(shù)據(jù)時,自動觸發(fā)
SQLAlchemy中的 session和scoped_session 的區(qū)別?
# Session:
由于無法提供線程共享功能,開發(fā)時要給每個線程都創(chuàng)建自己的session
打印sesion可知他是sqlalchemy.orm.session.Session的對象
# scoped_session:
為每個線程都創(chuàng)建一個session,實現(xiàn)支持線程安全
在整個程序運(yùn)行的過程當(dāng)中,只存在唯一的一個session對象。
創(chuàng)建方式:
? ?通過本地線程Threading.Local()
? ?# session=scoped_session(Session)
? ?創(chuàng)建唯一標(biāo)識的方法(參考flask請求源碼)
SQLAlchemy如何執(zhí)行原生SQL?
# 使用execute方法直接操作SQL語句(導(dǎo)入create_engin、sessionmaker)
engine=create_engine('mysql://root:*****@127.0.0.1/database?charset=utf8')
DB_Session = sessionmaker(bind=engine)
session = DB_Session()
session.execute('alter table mytablename drop column mycolumn ;')
ORM的實現(xiàn)原理?
# ORM的實現(xiàn)基于一下三點
映射類:描述數(shù)據(jù)庫表結(jié)構(gòu),
映射文件:指定數(shù)據(jù)庫表和映射類之間的關(guān)系
數(shù)據(jù)庫配置文件:指定與數(shù)據(jù)庫連接時需要的連接信息(數(shù)據(jù)庫、登錄用戶名、密碼or連接字符串)
DBUtils模塊的作用?
# 數(shù)據(jù)庫連接池
使用模式:
1、為每個線程創(chuàng)建一個連接,連接不可控,需要控制線程數(shù)
2、創(chuàng)建指定數(shù)量的連接在連接池,當(dāng)線程訪問的時候去取,不夠了線程排隊,直到有人釋放(推薦)
---------------------------------------------------------------------------
兩種寫法:
1、用靜態(tài)方法裝飾器,通過直接執(zhí)行類的方法來連接使用數(shù)據(jù)庫
2、通過實例化對象,通過對象來調(diào)用方法執(zhí)行語句
https://www.cnblogs.com/ArmoredTitan/p/Flask.html
以下SQLAlchemy的字段是否正確?如果不正確請更正:
from datetime import datetime from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Column, Integer, String, DateTimeBase = declarative_base() class UserInfo(Base):__tablename__ = 'userinfo' id = Column(Integer, primary_key=True, autoincrement=True)name = Column(String(64), unique=True) ctime = Column(DateTime, default=datetime.now()) ----------------------------------------------------------------------- 不正確:Ctime字段中參數(shù)應(yīng)為’default=datetime.now’now 后面不應(yīng)該加括號,加了的話,字段不會實時更新。SQLAchemy中如何為表設(shè)置引擎和字符編碼?
1. 設(shè)置引擎編碼方式為utf8。
engine = create_engine("mysql+pymysql://root:123456@127.0.0.1:3306/sqldb01?charset=utf8")
2. 設(shè)置數(shù)據(jù)庫表編碼方式為utf8
class UserType(Base):
__tablename__ = 'usertype'
id = Column(Integer, primary_key=True)
caption = Column(String(50), default='管理員')
# 添加配置設(shè)置編碼
__table_args__ = {
'mysql_charset':'utf8'
}
這樣生成的SQL語句就自動設(shè)置數(shù)據(jù)表編碼為utf8了,__table_args__還可設(shè)置存儲引擎、外鍵約束等等信息。
SQLAchemy中如何設(shè)置聯(lián)合唯一索引?
通過'UniqueConstraint'字段來設(shè)置聯(lián)合唯一索引
__table_args=(UniqueConstraint('h_id','username',name='_h_username_uc'))
#h_id和username組成聯(lián)合唯一約束
Tornado
簡述Tornado框架的特點。
異步非阻塞+websocket
簡述Tornado框架中Future對象的作用?
# 實現(xiàn)異步非阻塞 視圖函數(shù)yield一個futrue對象,futrue對象默認(rèn):self._done = False ,請求未完成self._result = None ,請求完成后返回值,用于傳遞給回調(diào)函數(shù)使用。tornado就會一直去檢測futrue對象的_done是否已經(jīng)變成True。如果IO請求執(zhí)行完畢,自動會調(diào)用future的set_result方法:self._result = resultself._done = True 參考:http://www.cnblogs.com/wupeiqi/p/6536518.html(自定義異步非阻塞web框架)Tornado框架中如何編寫WebSocket程序?
Tornado在websocket模塊中提供了一個WebSocketHandler類。 這個類提供了和已連接的客戶端通信的WebSocket事件和方法的鉤子。 當(dāng)一個新的WebSocket連接打開時,open方法被調(diào)用, 而on_message和on_close方法,分別在連接、接收到新的消息和客戶端關(guān)閉時被調(diào)用。此外,WebSocketHandler類還提供了write_message方法用于向客戶端發(fā)送消息,close方法用于關(guān)閉連接。Tornado中靜態(tài)文件是如何處理的??如: <link href="{{static_url("commons.css")}}" rel="stylesheet" />
# settings.py settings = {"static_path": os.path.join(os.path.dirname(__file__), "static"),# 指定了靜態(tài)文件的位置在當(dāng)前目錄中的"static"目錄下"cookie_secret": "61oETzKXQAGaYdkL5gEmGeJJFuYh7EQnp2XdTP1o/Vo=","login_url": "/login","xsrf_cookies": True, }經(jīng)上面配置后 static_url()自動去配置的路徑下找'commons.css'文件Tornado操作MySQL使用的模塊?
torndb torndb是基于mysqldb的再封裝,所以使用時要先安裝myqldbTornado操作redis使用的模塊?
tornado-redis簡述Tornado框架的適用場景?
web聊天室,在線投票git
git常見命令作用:
# git init初始化,當(dāng)前所在的文件夾可以被管理且以后版本相關(guān)的數(shù)據(jù)都會存儲到.git文件中 # git status查看當(dāng)前文件夾以及子目錄中文件是否發(fā)生變化:內(nèi)容修改/新增文件/刪除,已經(jīng)變化的文件會變成紅色,已經(jīng)add的文件會變成綠色 # git add .給發(fā)生變化的文件(貼上一個標(biāo)簽)或 將發(fā)生變化的文件放到某個地方,只寫一個句點符就代表把git status中紅色的文件全部打上標(biāo)簽 # git commit -m新增用戶登錄認(rèn)證功能以及xxx功能將“綠色”文件添加到版本中 # git log查看所有版本提交記錄,可以獲取版本號 # git reset --hard 版本號 將最新的版本回退到更早的版本 # git reflog 回退到之前版本后悔了,再更新到最新或者最新之前的版本 # git reset --hard 版本 回退簡述以下git中stash命令作用以及相關(guān)其他命令。
'git stash':將當(dāng)前工作區(qū)所有修改過的內(nèi)容存儲到“某個地方”,將工作區(qū)還原到當(dāng)前版本未修改過的狀態(tài) 'git stash list':查看“某個地方”存儲的所有記錄 'git stash clear':清空“某個地方” 'git stash pop':將第一個記錄從“某個地方”重新拿到工作區(qū)(可能有沖突) 'git stash apply':編號, 將指定編號記錄從“某個地方”重新拿到工作區(qū)(可能有沖突) 'git stash drop':編號,刪除指定編號的記錄git 中 merge 和 rebase命令 的區(qū)別。
merge: 會將不同分支的提交合并成一個新的節(jié)點,之前的提交分開顯示, 注重歷史信息、可以看出每個分支信息,基于時間點,遇到?jīng)_突,手動解決,再次提交 rebase: 將兩個分支的提交結(jié)果融合成線性,不會產(chǎn)生新的節(jié)點; 注重開發(fā)過程,遇到?jīng)_突,手動解決,繼續(xù)操作公司如何基于git做的協(xié)同開發(fā)?
1、你們公司的代碼review分支怎么做?誰來做? 答:組長創(chuàng)建review分支,我們小功能開發(fā)完之后,合并到review分支交給老大(小組長)來看, 1.1、你組長不開發(fā)代碼嗎?他開發(fā)代碼,但是它只開發(fā)核心的東西,任務(wù)比較少。或者抽出時間,我們一起做這個事情 2、你們公司協(xié)同開發(fā)是怎么協(xié)同開發(fā)的? 每個人都有自己的分支,階段性代碼完成之后,合并到review,然后交給老大看 -------------------------------------------------------------------------- # 大致工作流程 公司:下載代碼git clone https://gitee.com/wupeiqi/xianglong.git或創(chuàng)建目錄 cd 目錄 git init git remote add origin https://gitee.com/wupeiqi/xianglong.gitgit pull origin maste 創(chuàng)建dev分支git checkout dev git pull origin dev 繼續(xù)寫代碼git add . git commit -m '提交記錄'git push origin dev 回家: 拉代碼:git pull origin dev 繼續(xù)寫:繼續(xù)寫代碼git add . git commit -m '提交記錄'git push origin dev如何基于git實現(xiàn)代碼review?
https://blog.csdn.net/june_y/article/details/50817993git如何實現(xiàn)v1.0 、v2.0 等版本的管理?
在命令行中,使用“git tag –a tagname –m “comment”可以快速創(chuàng)建一個標(biāo)簽。 需要注意,命令行創(chuàng)建的標(biāo)簽只存在本地Git庫中,還需要使用Git push –tags指令發(fā)布到服務(wù)器的Git庫中github和gitlab的區(qū)別?
如何為github上牛逼的開源項目貢獻(xiàn)代碼?
1、fork需要協(xié)作項目 2、克隆/關(guān)聯(lián)fork的項目到本地 3、新建分支(branch)并檢出(checkout)新分支 4、在新分支上完成代碼開發(fā) 5、開發(fā)完成后將你的代碼合并到master分支 6、添加原作者的倉庫地址作為一個新的倉庫地址 7、合并原作者的master分支到你自己的master分支,用于和作者倉庫代碼同步 8、push你的本地倉庫到GitHub 9、在Github上提交 pull requests 10、等待管理員(你需要貢獻(xiàn)的開源項目管理員)處理git中 .gitignore文件的作用
一般來說每個Git項目中都需要一個“.gitignore”文件, 這個文件的作用就是告訴Git哪些文件不需要添加到版本管理中。實際項目中,很多文件都是不需要版本管理的,比如Python的.pyc文件和一些包含密碼的配置文件等等。敏捷開發(fā)
什么是敏捷開發(fā)?
'敏捷開發(fā)':是一種以人為核心、迭代、循序漸進(jìn)的開發(fā)方式。它并不是一門技術(shù),而是一種開發(fā)方式,也就是一種軟件開發(fā)的流程。 它會指導(dǎo)我們用規(guī)定的環(huán)節(jié)去一步一步完成項目的開發(fā)。 因為它采用的是迭代式開發(fā),所以這種開發(fā)方式的主要驅(qū)動核心是人簡述 jenkins 工具的作用?
'Jenkins'是一個可擴(kuò)展的持續(xù)集成引擎。主要用于:持續(xù)、自動地構(gòu)建/測試軟件項目。監(jiān)控一些定時執(zhí)行的任務(wù)。公司如何實現(xiàn)代碼發(fā)布?
nginx+uwsgi+django簡述 RabbitMQ、Kafka、ZeroMQ的區(qū)別?
https://blog.csdn.net/zhailihua/article/details/7899006RabbitMQ如何在消費者獲取任務(wù)后未處理完前就掛掉時,保證數(shù)據(jù)不丟失?
為了預(yù)防消息丟失,rabbitmq提供了ack 即工作進(jìn)程在收到消息并處理后,發(fā)送ack給rabbitmq,告知rabbitmq這時候可以把該消息從隊列中刪除了。 如果工作進(jìn)程掛掉 了,rabbitmq沒有收到ack,那么會把該消息 重新分發(fā)給其他工作進(jìn)程。 不需要設(shè)置timeout,即使該任務(wù)需要很長時間也可以處理。ack默認(rèn)是開啟的,工作進(jìn)程顯示指定了no_ack=TrueRabbitMQ如何對消息做持久化?
1、創(chuàng)建隊列和發(fā)送消息時將設(shè)置durable=Ture,如果在接收到消息還沒有存儲時,消息也有可能丟失,就必須配置publisher confirmchannel.queue_declare(queue='task_queue', durable=True)2、返回一個ack,進(jìn)程收到消息并處理完任務(wù)后,發(fā)給rabbitmq一個ack表示任務(wù)已經(jīng)完成,可以刪除該任務(wù)3、鏡像隊列:將queue鏡像到cluster中其他的節(jié)點之上。 在該實現(xiàn)下,如果集群中的一個節(jié)點失效了,queue能自動地切換到鏡像中的另一個節(jié)點以保證服務(wù)的可用性RabbitMQ如何控制消息被消費的順序?
默認(rèn)消息隊列里的數(shù)據(jù)是按照順序被消費者拿走, 例如:消費者1 去隊列中獲取奇數(shù)序列的任務(wù),消費者2去隊列中獲取偶數(shù)序列的任務(wù)。channel.basic_qos(prefetch_count=1) 表示誰來誰取,不再按照奇偶數(shù)排列(同時也保證了公平的消費分發(fā))以下RabbitMQ的exchange type分別代表什么意思?如:fanout、direct、topic。
amqp協(xié)議中的核心思想就是生產(chǎn)者和消費者隔離,生產(chǎn)者從不直接將消息發(fā)送給隊列。 生產(chǎn)者通常不知道是否一個消息會被發(fā)送到隊列中,只是將消息發(fā)送到一個交換機(jī)。 先由Exchange來接收,然后Exchange按照特定的策略轉(zhuǎn)發(fā)到Queue進(jìn)行存儲。 同理,消費者也是如此。Exchange 就類似于一個交換機(jī),轉(zhuǎn)發(fā)各個消息分發(fā)到相應(yīng)的隊列中。 -------------------------------------------------- type=fanout 類似發(fā)布者訂閱者模式,會為每一個訂閱者創(chuàng)建一個隊列,而發(fā)布者發(fā)布消息時,會將消息放置在所有相關(guān)隊列中 type=direct 隊列綁定關(guān)鍵字,發(fā)送者將數(shù)據(jù)根據(jù)關(guān)鍵字發(fā)送到消息exchange,exchange根據(jù) 關(guān)鍵字 判定應(yīng)該將數(shù)據(jù)發(fā)送至指定隊列。 type=topic 隊列綁定幾個模糊的關(guān)鍵字,之后發(fā)送者將數(shù)據(jù)發(fā)送到exchange,exchange將傳入”路由值“和 ”關(guān)鍵字“進(jìn)行匹配,匹配成功, 則將數(shù)據(jù)發(fā)送到指定隊列。 --------------------------------------------------- 發(fā)送者路由值 隊列中 old.boy.python old.* -- 不匹配 *表示匹配一個 old.boy.python old.# -- 匹配 #表示匹配0個或多個celery
簡述 celery 是什么以及應(yīng)用場景?
# Celery是由Python開發(fā)的一個簡單、靈活、可靠的處理大量任務(wù)的分發(fā)系統(tǒng), # 它不僅支持實時處理也支持任務(wù)調(diào)度。 # http://www.cnblogs.com/wupeiqi/articles/8796552.html簡述celery運(yùn)行機(jī)制。
celery如何實現(xiàn)定時任務(wù)?
# celery實現(xiàn)定時任務(wù) 啟用Celery的定時任務(wù)需要設(shè)置CELERYBEAT_SCHEDULE 。 CELERYBEAT_SCHEDULE='djcelery.schedulers.DatabaseScheduler'#定時任務(wù) '創(chuàng)建定時任務(wù)' # 通過配置CELERYBEAT_SCHEDULE: #每30秒調(diào)用task.add from datetime import timedelta CELERYBEAT_SCHEDULE = {'add-every-30-seconds': {'task': 'tasks.add','schedule': timedelta(seconds=30),'args': (16, 16)}, }簡述 celery多任務(wù)結(jié)構(gòu)目錄
pro_cel├── celery_tasks # celery相關(guān)文件夾│ ├── celery.py # celery連接和配置相關(guān)文件│ └── tasks.py # 所有任務(wù)函數(shù)├── check_result.py # 檢查結(jié)果└── send_task.py # 觸發(fā)任務(wù)celery中裝飾器 @app.task 和 @shared_task的區(qū)別?
# 一般情況使用的是從celeryapp中引入的app作為的裝飾器:@app.task # django那種在app中定義的task則需要使用@shared_task簡述?requests模塊的作用及基本使用?
# 作用: 使用requests可以模擬瀏覽器的請求 # 常用參數(shù):url、headers、cookies、datajson、params、proxy # 常用返回值:contentiter_contenttext encoding="utf-8"cookie.get_dict()簡述 beautifulsoup模塊的作用及基本使用?
# BeautifulSoup 用于從HTML或XML文件中提取、過濾想要的數(shù)據(jù)形式 #常用方法 解析:html.parser 或者 lxml(需要下載安裝) find、find_all、text、attrs、get簡述 seleninu模塊的作用及基本使用?
Selenium是一個用于Web應(yīng)用程序測試的工具, 他的測試直接運(yùn)行在瀏覽器上,模擬真實用戶,按照代碼做出點擊、輸入、打開等操作爬蟲中使用他是為了解決requests無法解決javascript動態(tài)問題scrapy
scrapy框架中各組件的工作流程?
#1、生成初始的Requests來爬取第一個URLS,并且標(biāo)識一個回調(diào)函數(shù) 第一個請求定義在start_requests()方法內(nèi)默認(rèn)從start_urls列表中獲得url地址來生成Request請求, 默認(rèn)的回調(diào)函數(shù)是parse方法。回調(diào)函數(shù)在下載完成返回response時自動觸發(fā) #2、在回調(diào)函數(shù)中,解析response并且返回值 返回值可以4種:a、包含解析數(shù)據(jù)的字典b、Item對象c、新的Request對象(新的Requests也需要指定一個回調(diào)函數(shù))d、或者是可迭代對象(包含Items或Request) #3、在回調(diào)函數(shù)中解析頁面內(nèi)容 通常使用Scrapy自帶的Selectors,但很明顯你也可以使用Beutifulsoup,lxml或其他你愛用啥用啥。 #4、最后,針對返回的Items對象將會被持久化到數(shù)據(jù)庫通過Item Pipeline組件存到數(shù)據(jù)庫或者導(dǎo)出到不同的文件(通過Feed exports) http://www.cnblogs.com/wupeiqi/articles/6229292.html在scrapy框架中如何設(shè)置代理(兩種方法)?
方式一:內(nèi)置添加代理功能 # -*- coding: utf-8 -*- import os import scrapy from scrapy.http import Requestclass ChoutiSpider(scrapy.Spider):name = 'chouti'allowed_domains = ['chouti.com']start_urls = ['https://dig.chouti.com/']def start_requests(self):os.environ['HTTP_PROXY'] = "http://192.168.11.11"for url in self.start_urls:yield Request(url=url,callback=self.parse)def parse(self, response):print(response)方式二:自定義下載中間件 import random import base64 import six def to_bytes(text, encoding=None, errors='strict'):"""Return the binary representation of `text`. If `text`is already a bytes object, return it as-is."""if isinstance(text, bytes):return textif not isinstance(text, six.string_types):raise TypeError('to_bytes must receive a unicode, str or bytes ''object, got %s' % type(text).__name__)if encoding is None:encoding = 'utf-8'return text.encode(encoding, errors)class MyProxyDownloaderMiddleware(object):def process_request(self, request, spider):proxy_list = [{'ip_port': '111.11.228.75:80', 'user_pass': 'xxx:123'},{'ip_port': '120.198.243.22:80', 'user_pass': ''},{'ip_port': '111.8.60.9:8123', 'user_pass': ''},{'ip_port': '101.71.27.120:80', 'user_pass': ''},{'ip_port': '122.96.59.104:80', 'user_pass': ''},{'ip_port': '122.224.249.122:8088', 'user_pass': ''},]proxy = random.choice(proxy_list)if proxy['user_pass'] is not None:request.meta['proxy'] = to_bytes("http://%s" % proxy['ip_port'])encoded_user_pass = base64.encodestring(to_bytes(proxy['user_pass']))request.headers['Proxy-Authorization'] = to_bytes('Basic ' + encoded_user_pass)else:request.meta['proxy'] = to_bytes("http://%s" % proxy['ip_port'])配置:DOWNLOADER_MIDDLEWARES = {# 'xiaohan.middlewares.MyProxyDownloaderMiddleware': 543,}scrapy框架中如何實現(xiàn)大文件的下載?
from twisted.web.client import Agent, getPage, ResponseDone, PotentialDataLoss from twisted.internet import defer, reactor, protocol from twisted.web._newclient import Response from io import BytesIOclass _ResponseReader(protocol.Protocol):def __init__(self, finished, txresponse, file_name):self._finished = finishedself._txresponse = txresponseself._bytes_received = 0self.f = open(file_name, mode='wb')def dataReceived(self, bodyBytes):self._bytes_received += len(bodyBytes)# 一點一點的下載self.f.write(bodyBytes)self.f.flush()def connectionLost(self, reason):if self._finished.called:returnif reason.check(ResponseDone):# 下載完成self._finished.callback((self._txresponse, 'success'))elif reason.check(PotentialDataLoss):# 下載部分self._finished.callback((self._txresponse, 'partial'))else:# 下載異常self._finished.errback(reason)self.f.close()scrapy中如何實現(xiàn)限速?
http://scrapy-chs.readthedocs.io/zh_CN/1.0/topics/autothrottle.htmlscrapy中如何實現(xiàn)暫停爬蟲?
# 有些情況下,例如爬取大的站點,我們希望能暫停爬取,之后再恢復(fù)運(yùn)行。 # Scrapy通過如下工具支持這個功能: 一個把調(diào)度請求保存在磁盤的調(diào)度器 一個把訪問請求保存在磁盤的副本過濾器[duplicates filter] 一個能持續(xù)保持爬蟲狀態(tài)(鍵/值對)的擴(kuò)展 Job 路徑 要啟用持久化支持,你只需要通過 JOBDIR 設(shè)置 job directory 選項。 這個路徑將會存儲所有的請求數(shù)據(jù)來保持一個單獨任務(wù)的狀態(tài)(例如:一次spider爬取(a spider run))。 必須要注意的是,這個目錄不允許被不同的spider 共享,甚至是同一個spider的不同jobs/runs也不行。 也就是說,這個目錄就是存儲一個 單獨 job的狀態(tài)信息。scrapy中如何進(jìn)行自定制命令?
在spiders同級創(chuàng)建任意目錄,如:commands 在其中創(chuàng)建'crawlall.py'文件(此處文件名就是自定義的命令) from scrapy.commands import ScrapyCommandfrom scrapy.utils.project import get_project_settingsclass Command(ScrapyCommand):requires_project = Truedef syntax(self):return '[options]'def short_desc(self):return 'Runs all of the spiders'def run(self, args, opts):spider_list = self.crawler_process.spiders.list()for name in spider_list:self.crawler_process.crawl(name, **opts.__dict__)self.crawler_process.start() 在'settings.py'中添加配置'COMMANDS_MODULE = '項目名稱.目錄名稱'' 在項目目錄執(zhí)行命令:'scrapy crawlall'scrapy中如何實現(xiàn)的記錄爬蟲的深度?
'DepthMiddleware'是一個用于追蹤每個Request在被爬取的網(wǎng)站的深度的中間件。 其可以用來限制爬取深度的最大深度或類似的事情。 'DepthMiddleware'可以通過下列設(shè)置進(jìn)行配置(更多內(nèi)容請參考設(shè)置文檔):'DEPTH_LIMIT':爬取所允許的最大深度,如果為0,則沒有限制。 'DEPTH_STATS':是否收集爬取狀態(tài)。 'DEPTH_PRIORITY':是否根據(jù)其深度對requet安排優(yōu)先scrapy中的pipelines工作原理?
Scrapy 提供了 pipeline 模塊來執(zhí)行保存數(shù)據(jù)的操作。 在創(chuàng)建的 Scrapy 項目中自動創(chuàng)建了一個 pipeline.py 文件,同時創(chuàng)建了一個默認(rèn)的 Pipeline 類。 我們可以根據(jù)需要自定義 Pipeline 類,然后在 settings.py 文件中進(jìn)行配置即可scrapy的pipelines如何丟棄一個item對象?
通過raise DropItem()方法
簡述scrapy中爬蟲中間件和下載中間件的作用?1
http://www.cnblogs.com/wupeiqi/articles/6229292.htmlscrapy-redis組件的作用?
實現(xiàn)了分布式爬蟲,url去重、調(diào)度器、數(shù)據(jù)持久化 'scheduler'調(diào)度器 'dupefilter'URL去重規(guī)則(被調(diào)度器使用) 'pipeline'數(shù)據(jù)持久化scrapy-redis組件中如何實現(xiàn)的任務(wù)的去重?
a.?內(nèi)部進(jìn)行配置,連接Redis
b.去重規(guī)則通過redis的集合完成,集合的Key為:
???key?=?defaults.DUPEFILTER_KEY?%?{'timestamp':?int(time.time())}
???默認(rèn)配置:
??????DUPEFILTER_KEY?=?'dupefilter:%(timestamp)s'
c.去重規(guī)則中將url轉(zhuǎn)換成唯一標(biāo)示,然后在redis中檢查是否已經(jīng)在集合中存在
???from?scrapy.utils?import?request
???from?scrapy.http?import?Request
???req?=?Request(url='http://www.cnblogs.com/wupeiqi.html')
???result?=?request.request_fingerprint(req)
???print(result) ?# 8ea4fd67887449313ccc12e5b6b92510cc53675c
scrapy-redis的調(diào)度器如何實現(xiàn)任務(wù)的深度優(yōu)先和廣度優(yōu)先?....
簡述 vitualenv?及應(yīng)用場景?
'vitualenv'是一個獨立的python虛擬環(huán)境 如:當(dāng)前項目依賴的是一個版本,但是另一個項目依賴的是另一個版本,這樣就會造成依賴沖突,而virtualenv就是解決這種情況的,virtualenv通過創(chuàng)建一個虛擬化的python運(yùn)行環(huán)境,將我們所需的依賴安裝進(jìn)去的,不同項目之間相互不干擾簡述 pipreqs 及應(yīng)用場景?
可以通過對項目目錄掃描,自動發(fā)現(xiàn)使用了那些類庫,并且自動生成依賴清單。pipreqs ./ 生成requirements.txt在Python中使用過什么代碼檢查工具?
1)PyFlakes:靜態(tài)檢查Python代碼邏輯錯誤的工具。 2)Pep8: 靜態(tài)檢查PEP8編碼風(fēng)格的工具。 3)NedBatchelder’s McCabe script:靜態(tài)分析Python代碼復(fù)雜度的工具。 Python代碼分析工具:PyChecker、Pylint簡述 saltstack、ansible、fabric、puppet工具的作用?
?
B Tree和B+ Tree的區(qū)別?
1.B樹中同一鍵值不會出現(xiàn)多次,并且有可能出現(xiàn)在葉結(jié)點,也有可能出現(xiàn)在非葉結(jié)點中。而B+樹的鍵一定會出現(xiàn)在葉結(jié)點中,并有可能在非葉結(jié)點中重復(fù)出現(xiàn),以維持B+樹的平衡。 2.因為B樹鍵位置不定,且在整個樹結(jié)構(gòu)中只出現(xiàn)一次,請列舉常見排序并通過代碼實現(xiàn)任意三種。
算法基礎(chǔ)之排序
?請列舉常見查找并通過代碼實現(xiàn)任意三種。
無序查找、二分查找、插值查找
請列舉你熟悉的設(shè)計模式?
工廠模式/單例模式等有沒有刷過leetcode?
leetcode是個題庫,里面有多很編程題目,可以在線編譯運(yùn)行。
https://leetcode-cn.com/problemset/all/
列舉熟悉的的Linux命令。
公司線上服務(wù)器是什么系統(tǒng)?
linux/centos7
解釋 PV、UV 的含義?
PV訪問量(Page View),即頁面訪問量,每打開一次頁面PV計數(shù)+1,刷新頁面也是。
UV訪問數(shù)(Unique Visitor)指獨立訪客訪問數(shù),一臺電腦終端為一個訪客。
解釋 QPS的含義?
'QPS(Query Per Second)'每秒查詢率,是對一個特定的查詢服務(wù)器在規(guī)定時間內(nèi)所處理流量多少的衡量標(biāo)準(zhǔn)
uwsgi和wsgi的區(qū)別?
wsgi是一種通用的接口標(biāo)準(zhǔn)或者接口協(xié)議,實現(xiàn)了python web程序與服務(wù)器之間交互的通用性。uwsgi:同WSGI一樣是一種通信協(xié)議 uwsgi協(xié)議是一個'uWSGI服務(wù)器'自有的協(xié)議,它用于定義傳輸信息的類型, 'uWSGI'是實現(xiàn)了uwsgi和WSGI兩種協(xié)議的Web服務(wù)器,負(fù)責(zé)響應(yīng)python的web請求。supervisor的作用?
# Supervisor: 是一款基于Python的進(jìn)程管理工具,可以很方便的管理服務(wù)器上部署的應(yīng)用程序。 是C/S模型的程序,其服務(wù)端是supervisord服務(wù),客戶端是supervisorctl命令# 主要功能: 1 啟動、重啟、關(guān)閉包括但不限于python進(jìn)程。 2 查看進(jìn)程的運(yùn)行狀態(tài)。 3 批量維護(hù)多個進(jìn)程。什么是反向代理?
正向代理代理客戶端(客戶端找喲個代理去訪問服務(wù)器,服務(wù)器不知道你的真實IP) 反向代理代理服務(wù)器(服務(wù)器找一個代理給你響應(yīng),你不知道服務(wù)器的真實IP)簡述SSH的整個過程。
SSH 為 'Secure Shell' 的縮寫,是建立在應(yīng)用層基礎(chǔ)上的安全協(xié)議。 SSH 是目前較可靠,為遠(yuǎn)程登錄會話和其他網(wǎng)絡(luò)服務(wù)提供的安全性協(xié)議。 利用 SSH 協(xié)議可以有效防止遠(yuǎn)程管理過程中的信息泄露問題。有問題都去那些找解決方案?
起初是百度,發(fā)現(xiàn)搜到的答案不精準(zhǔn),凈廣告 轉(zhuǎn)戰(zhàn)谷歌,但墻了;搗鼓怎么FQ還會去知乎、stackoverfloow、必應(yīng)、思否(segmentfault)是否有關(guān)注什么技術(shù)類的公眾號?
python之禪(主要專注Python相關(guān)知識,作者:劉志軍) 碼農(nóng)翻身(主要是Java的,但不光是java,涵蓋面很廣,作者:劉欣) 實驗樓(在線練項目) and so on最近在研究什么新技術(shù)?
Numpy pandas(金融量化分析、聚寬) 百度AI 圖靈API 智能玩具是否了解過領(lǐng)域驅(qū)動模型?
Domain-Driven Design?
二進(jìn)制與十進(jìn)制之間的轉(zhuǎn)換
1、十進(jìn)制 與 二進(jìn)制之間的轉(zhuǎn)換
??? (1)、十進(jìn)制轉(zhuǎn)換為二進(jìn)制,分為整數(shù)部分和小數(shù)部分
整數(shù)部分
方法:除2取余法,即每次將整數(shù)部分除以2,余數(shù)為該位權(quán)上的數(shù),而商繼續(xù)除以2,余數(shù)又為上一個位權(quán)上的數(shù)。 這個步驟一直持續(xù)下去,直到商為0為止,最后讀數(shù)時候,從最后一個余數(shù)讀起,一直到最前面的一個余數(shù)。下面舉例:例:將十進(jìn)制的168轉(zhuǎn)換為二進(jìn)制 得出結(jié)果 將十進(jìn)制的168轉(zhuǎn)換為二進(jìn)制,(10101000)2 168 / 2 = 84 -- 0 84 / 2 = 42 -- 0 42 / 2 = 21 -- 0 21 / 2 = 10 -- 1 10 / 2 = 5 -- 05 / 2 = 2 -- 1 2 / 2 = 1 -- 0 1 / 2 = 0 -- 1 二進(jìn)制(從后往前讀): 10101000小數(shù)部分
方法:乘2取整法,即將小數(shù)部分乘以2,然后取整數(shù)部分,剩下的小數(shù)部分繼續(xù)乘以2,然后取整數(shù)部分, 剩下的小數(shù)部分又乘以2,一直取到小數(shù)部分為零為止。如果永遠(yuǎn)不能為零,就同十進(jìn)制數(shù)的四舍五入一樣, 按照要求保留多少位小數(shù)時,就根據(jù)后面一位是0還是1,取舍,如果是零,舍掉,如果是1,向入一位。 換句話說就是0舍1入。讀數(shù)要從前面的整數(shù)讀到后面的整數(shù)二進(jìn)制轉(zhuǎn)換為十進(jìn)制 (不分整數(shù)和小數(shù)部分)
方法:按權(quán)相加法,即將二進(jìn)制每位上的數(shù)乘以權(quán),然后相加之和即是十進(jìn)制數(shù)。
例:將二進(jìn)制數(shù)101.101轉(zhuǎn)換為十進(jìn)制數(shù)。 得出結(jié)果:(101.101)2=(5.625)10 在做二進(jìn)制轉(zhuǎn)換成十進(jìn)制需要注意的是 1)要知道二進(jìn)制每位的權(quán)值 2)要能求出每位的值 101.101 轉(zhuǎn)換為十進(jìn)制 整數(shù)部分:2^2 + 2^0 = 5 小數(shù)部分:2^(-1) + 2^(-3) = 1/2 + 1/8 = 0.5 + 0.125 = 0.625 十進(jìn)制: 2^2 + 2^0 + 2^(-1) + 2^(-3) = 5.625總結(jié)
以上是生活随笔為你收集整理的面试之 Python 进阶的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 锋利的jQuery--Ajax(读书笔记
- 下一篇: Python 第三方模块之 numpy.