#### django、flask、tornado框架的比較?
django:
優點:最全能的web開發框架,各種功能完備,可維護性高,開發速度快
缺點:django orm 跟數據庫的交互,django同步特性導致吞吐量小的問題可以通過celery解決
tornado:
優點:天生異步,性能強悍
缺點:框架提供的功能比較少,需要自己實現,這樣導致了開發速度偏慢
flask:
優點:自由、靈活,擴展性強,第三方庫的選擇面廣
缺點:但是對程序員要求更高
---
#### 什么是wsgi?
https://www.jianshu.com/p/679dee0a4193
WSGI,描述web server如何與web application通信的一種規范
WSGI協議主要包括server和application兩部分:
WSGI server負責從客戶端接收請求,將request轉發給application,將application返回的response返回給客戶端;
WSGI application接收由server轉發的request,處理請求,并將處理結果返回給server。
application中可以包括多個棧式的中間件(middlewares),這些中間件需要同時實現server與application,因此可以在WSGI服務器與WSGI應用之間起調節作用:對服務器來說,中間件扮演應用程序,對應用程序來說,中間件扮演服務器。
---
#### django請求的生命周期?
Django的請求生命周期是指當用戶在瀏覽器上輸入url到用戶看到網頁的這個時間段內,Django后臺所發生的事情
而Django的生命周期內到底發生了什么呢??
1. 當用戶在瀏覽器中輸入url時,瀏覽器會生成請求頭和請求體發給服務端
請求頭和請求體中會包含瀏覽器的動作(action),這個動作通常為get或者post,體現在url之中.
2. url經過Django中的wsgi,再經過Django的中間件,最后url到過路由映射表,在路由中一條一條進行匹配,
一旦其中一條匹配成功就執行對應的視圖函數,后面的路由就不再繼續匹配了.
3. 視圖函數根據客戶端的請求查詢相應的數據.返回給Django,然后Django把客戶端想要的數據做為一個字符串返回給客戶端.
4. 客戶端瀏覽器接收到返回的數據,經過渲染后顯示給用戶.
---
#### 列舉django的內置組件
認證組件
緩存
日志
郵件
分頁
靜態文件管理
資訊聚合
消息框架
數據驗證
---
#### 列舉django中間件的5個方法?以及django中間件的應用場景?
在django中,中間件其實就是一個類,在請求到來和結束后,django會根據自己的規則在合適的時機執行中間件中相應的方法
在django項目的settings模塊中,有一個 MIDDLEWARE_CLASSES 變量,其中每一個元素就是一個中間件
默認的中間件有哪些
中間件中可以定義五個方法,分別是:
```python
# 方法在請求到來的時候調用
process_request(self,request)
# 在本次將要執行的View函數被調用前調用本函數
process_view(self, request, callback, callback_args, callback_kwargs)
# 需使用render()方法才會執行process_template_response
process_template_response(self,request,response)
# View函數在拋出異常時該函數被調用,得到的exception參數是實際上拋出的異常實例。通過此方法可以進行很好的錯誤控制,提供友好的用戶界面。
process_exception(self, request, exception)
# 在執行完View函數準備將響應發到客戶端前被執行
process_response(self, request, response)
```
django中間件的使用場景
如果你想修改請求,例如被傳送到view中的HttpRequest對象
或者你想修改view返回的HttpResponse對象,這些都可以通過中間件來實現
可能你還想在view執行之前做一些操作,這種情況也可以用 middleware來實現。
比如我們寫一個判斷瀏覽器來源,是pc還是手機,這里手機我們采用iphone,因為暫時沒有其他設備。我們有不想把這個邏輯加到視圖函數里,想作為一個通用服務,作為一個可插拔的組件被使用,最好的方法就是實現為中間件
或者說做一個攔截器,發現一定的時間內某個ip對網頁的訪問次數過多,則將其加入黑名單
---
#### 簡述什么是FBV和CBV?
FBV(function base views) 基于函數的視圖
CBV(class base views) 基于類的視圖
使用fbv的模式,在url匹配成功之后,會直接執行對應的視圖函數
使用cbv模式,在url匹配成功之后,會找到視圖函數中對應的類,然后這個類回到請求頭中找到對應的Request Method
用戶發送url請求,Django會依次遍歷路由映射表中的所有記錄,一旦路由映射表其中的一條匹配成功了,就執行視圖函數中對應的函數名,這是fbv的執行流程
當服務端使用cbv模式的時候,用戶發給服務端的請求包含url和method,這兩個信息都是字符串類型
服務端通過路由映射表匹配成功后會自動去找dispatch方法,然后Django會通過dispatch反射的方式找到類中對應的方法并執行
類中的方法執行完畢之后,會把客戶端想要的數據返回給dispatch方法,由dispatch方法把數據返回經客戶端
---
#### django的request對象是在什么時候創建的?
當請求一個頁面時,Django創建一個 HttpRequest 對象.該對象包含 request 的元數據. 然后 Django 調用相應的 view 函數(HttpRequest 對象自動傳遞給該view函數<作為第一個參數>), 每一個 view 負責返回一個 HttpResponse 對象.
requests的元數據包括path,get,put等方法,cookies,user等等
---
#### 如何給CBV的程序添加裝飾器?
CBV添加裝飾器有兩種方法
1. 在指定方法上添加裝飾器
2. 在類上添加,但是要用name來指定方法
```python
## CBV中添加裝飾器
def wrapper(func):
def inner(*args,**kwargs):
return func(*args,**kwargs)
return inner
# 1. 指定方法上添加裝飾器
class Foo(View):
@method_decorator(wrapper)
def get(self,request):
pass
def post(self,request):
pass
2. 在類上添加
@method_decorator(wrapper,name='dispatch')
class Foo(View):
def get(self,request):
pass
def post(self,request):
pass
```
總結
1. 添加裝飾器前必須導入from django.utils.decorators import method_decorator
2. 添加裝飾器的格式必須為@method_decorator(),括號里面為裝飾器的函數名
3. 給類添加是必須聲明name
4. 注意csrf-token裝飾器的特殊性,它只能加在dispatch上面
---
#### 列舉django orm 中所有的方法(QuerySet對象的所有方法)
從數據庫中查詢出來的結果一般是一個集合,這個集合叫做 QuerySet
- filter 過濾
- exclude 排除
- annotate 聚合
- order_by 排序
- reverse 反向排序
- distinct 去除查詢結果中重復的行
- values 迭代時返回字典而不是模型實例對象
- values_list 迭代時返回元組而不是字典
- dates 表示特定種類的所有可用日期
- datetimes 表示特定種類的所有可用日期
- none 不返回任何對象
- all 返回所有結果
- select_related 外鍵查詢
- prefetch_related 在單個批處理中自動檢索每個指定查找的相關對象
- defer 告訴django不要查詢某些字段
- using 多個數據庫時控制QuerySet在哪個數據庫上求值
---
#### only和defer的區別?
在復雜的情況下,表中可能有些字段內容非常多,取出來轉化成 Python 對象會占用大量的資源。
這時候可以用 defer 來排除這些字段,比如我們在文章列表頁,只需要文章的標題和作者,沒有必要把文章的內容也獲取出來(因為會轉換成python對象,浪費內存)
和 defer 相反,only 用于取出需要的字段,假如我們只需要查出 作者的名稱
---
#### `select_related`和`prefetch_related`的區別?
https://hk.saowen.com/a/bb124ab70580b722d7840c7c0377a326ac4ce022dc653f4cbc7e0ae7fc245232
---
#### filter和exclude的區別?
filter 設置要查詢的字段
exclude 設置不要查詢的字段
---
#### 列舉django orm中三種能寫sql語句的方法
1. 使用extra:查詢人民郵電出版社出版并且價格大于50元的書籍
```python
Book.objects.filter(publisher__name='人民郵電出版社').extra(where=['price>50'])
```
2. 使用raw
```python
books=Book.objects.raw('select * from hello_book')
for book in books:
print book
```
3. 自定義sql
```python
from django.db import connection
cursor = connection.cursor()
cursor.execute("insert into hello_author(name) VALUES ('郭敬明')")
cursor.execute("update hello_author set name='韓寒' WHERE name='郭敬明'")
cursor.execute("delete from hello_author where name='韓寒'")
cursor.execute("select * from hello_author")
cursor.fetchone()
cursor.fetchall()
```
---
#### django orm 中如何設置讀寫分離?
https://blog.csdn.net/Ayhan_huang/article/details/78784486
https://my.oschina.net/candiesyangyang/blog/203425
---
#### F和Q的作用?
F作用:操作數據表中的某列值,F()允許Django在未實際鏈接數據的情況下具有對數據庫字段的值的引用,不用獲取對象放在內存中再對字段進行操作,直接執行原生產sql語句操作
使用場景:對數據庫中的所有的商品,在原價格的基礎上漲價10元
```python
from django.db.models import F
from app01.models import Book
Book.objects.update(price=F("price")+20) # 對于book表中每本書的價格都在原價格的基礎上增加20元
```
Q作用:對對象進行復雜查詢,并支持&(and),|(or),~(not)操作符
使用場景:filter查詢條件只有一個,而使用Q可以設置多個查詢條件
```python
from django.db.models import Q
search_obj=Asset.objects.filter(Q(hostname__icontains=keyword)|Q(ip=keyword))
```
當同時使用filter的關鍵字查詢和Q查詢時,一定要把Q對象放在前面
```python
Asset.objects.get(
Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)),question__startswith='Who')
```
#### values和values_list的區別
values 返回字典而不是模型查詢對象
values-list 跟values一樣,但是返回的是元組
https://blog.csdn.net/weixin_40475396/article/details/79529256
#### 如何使用django orm批量創建數據?
如果使用django save()創建數據,則每次save的時候都會訪問一次數據庫
```python
for i in resultlist:
p = Account(name=i)
p.save()
```
django1.4之后加入新特性可以批量創建對象,減少SQL查詢次數
```python
querysetlist=[]
for i in resultlist:
querysetlist.append(Account(name=i))
Account.objects.bulk_create(querysetlist)
```
#### django的Form和ModeForm的作用?
http://www.cnblogs.com/caochao-/articles/8412830.html
表單的作用是收集元素中的內容
Form 需要自己定義表單的字段
ModelForm 根據model來生成表單的字段
#### django的Form組件中,如果字段中包含choices參數,請使用兩種方式實現數據源實時更新
此問題只適用于From組件,ModelFrom組件不用考慮(自身已經解決)
示例:例如choice類型字段,添加了新的數據,而在頁面中不能顯示出來,只有再次刷新頁面才能獲取最新的數據,因為程序運行時靜態字段只加載一次, choice的數據如果從數據庫獲取可能會造成數據無法實時更新
```python
# models.py
from django.db import models
class UserType(models.Model):
title = models.CharField(max_length=32)
def __str__(self):
return self.title
class UserInfo(models.Model):
name = models.CharField(max_length=32)
email = models.CharField(max_length=32)
ut = models.ForeignKey(to='UserType')
```
方法一:重寫構造方法:
```python
# views.py
from django.forms import Form
from django.forms import fields
class UserForm(Form):
name = fields.CharField(label='用戶名',max_length=32)
email = fields.EmailField(label='郵箱')
ut_id = fields.ChoiceField(
# choices=[(1,'二筆用戶'),(2,'悶騷')]
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')
def user(request):
if request.method == "GET":
form = UserForm()
return render(request,'user.html',{'form':form})
```
方法二:使用ModelChoiceField字段
```python
# views.py
from django.forms import Form
from django.forms import fields
from django.forms.models import ModelChoiceField
class UserForm(Form):
name = fields.CharField(label='用戶名',max_length=32)
email = fields.EmailField(label='郵箱')
ut_id = ModelChoiceField(queryset=models.UserType.objects.all())
```
#### django的Model中的ForeignKey字段中的on_delete參數有什么作用?
當一個被ForeignKey引用的對象刪除后,django將會通過指定on_delete參數來仿真sql約束的行為
例如,如果你有一個可以為空的ForeignKey,在其引用的對象被刪除的時你想把這個ForeignKey 設置為空:
```python
user = models.ForeignKey(User, blank=True, null=True, on_delete=models.SET_NULL)
```
`on_delete`有`CASCADE`、`PROTECT`、`SET_NULL`、`SET_DEFAULT`、`SET()`五個可選擇的值
1. CASCADE: 級聯刪除;默認值
2. PROTECT: 拋出ProtectedError 以阻止被引用對象的刪除,它是django.db.IntegrityError 的一個子類
3. SET_NULL: 把ForeignKey 設置為null; null 參數為True 時才可以這樣做
4. SET_DEFAULT: ForeignKey 值設置成它的默認值;此時必須設置ForeignKey 的default 參數
5. SET: 設置ForeignKey 為傳遞給SET() 的值,如果傳遞的是一個可調用對象,則為調用后的結果。在大部分情形下,傳遞一個可調用對象用于避免models.py 在導入時執行查詢
#### django中csrf的實現機制?
https://blog.csdn.net/u011715678/article/details/48752873
https://www.jianshu.com/p/991df812e2a5?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation
#### django如何實現websocket?
http://www.ruanyifeng.com/blog/2017/05/websocket.html
HTTP 協議有一個缺陷:通信只能由客戶端發起
WebSocket 協議它的最大特點就是,服務器可以主動向客戶端推送信息,客戶端也可以主動向服務器發送信息,是真正的雙向平等對話,屬于服務器推送技術的一種
django實現websocket有多種方式:
1. 使用Channels實現websocket
https://www.jianshu.com/p/3de90e457bb4
2. 使用dwebsocket實現Websocket
https://www.cnblogs.com/huguodong/p/6611602.html
http://gtcsq.readthedocs.io/en/latest/others/websocket.html
#### 基于django使用ajax發送post請求時,都可以使用哪種方法攜帶csrf token?
1、寫在Ajax beforeSend
```
ajax({
xxx:xxx,
beforeSend:function(xhr, settings){
xhr.setRequestHeader("x-CSRFToken", "{{ csrf_token }}");
},
})
```
2、寫到Ajax Data
```
ajax({
xxx:xxx,
data: $("#form").serialize(),
})
```
3、寫到ajaxSetup
```
$("#add-business-form").submit(function () {
$.ajaxSetup({
data: {csrfmiddlewaretoken: '{{ csrf_token }}'}
});
$.ajax({
xxx:xxxx,
});
return false;
});
```
4、KindEditor攜帶CSRF
```
<script>
var csrfitems = document.getElementsByName("csrfmiddlewaretoken");
var csrftoken = "";
if(csrfitems.length > 0)
{
csrftoken = csrfitems[0].value;
}
$(function () {
initKindEditor();
});
function initKindEditor() {
$.ajaxSetup({
data: {csrfmiddlewaretoken: '{{ csrf_token }}'}
});
var kind = KindEditor.create('#content', {
width: '100%', // 文本框寬度(可以百分比或像素)
height: '300px', // 文本框高度(只能像素)
minWidth: 200, // 最小寬度(數字)
minHeight: 400, // 最小高度(數字)
uploadJson: '{% url "upload_image" %}',
extraFileUploadParams : {
csrfmiddlewaretoken:csrftoken
}
});
}
</script>
```
#### django中如何實現orm表中添加數據時創建一條日志記錄
1. 使用信號記錄
2. 使用logger
https://blog.csdn.net/apple9005/article/details/73608994
#### django緩存如何設置?
https://www.cnblogs.com/linxiyue/p/7494540.html
#### django的緩存能使用redis嗎?如果可以的話,如何配置?
https://www.jianshu.com/p/04ef84c3fe3b
#### django路由系統中name的作用?
https://www.cnblogs.com/no13bus/p/3767521.html
https://code.ziqiangxuetang.com/django/django-url-name.html
#### django的模板中filter和simple_tag的區別?
https://blog.csdn.net/huanhuanq1209/article/details/77756446
#### django-debug-toolbar的作用?
https://www.cnblogs.com/Lands-ljk/p/5506766.html
#### django中如何實現單元測試?
https://www.jianshu.com/p/15af33d2c2c4
#### 解釋orm中 db first 和 code first的含義
db first:現有數據庫,然后從數據庫反向生成models.py
code first: 現有models.py 再進行數據庫操作
#### django中如何根據數據庫表生成model中的類
https://www.jianshu.com/p/037bd7e20a7a
#### 使用orm和原生sql的優缺點?
使用 ORM 最大的優點就是快速開發,讓我們將更多的精力放在業務上而不是數據庫上,下面是 ORM 的幾個優點
1. 隱藏了數據訪問細節,使通用數據庫交互變得簡單易行。同時 ORM 避免了不規范、冗余、風格不統一的 SQL 語句,可以避免很多人為的 bug,方便編碼風格的統一和后期維護。
2. 將數據庫表和對象模型關聯,我們只需針對相關的對象模型進行編碼,無須考慮對象模型和數據庫表之間的轉化,大大提高了程序的開發效率。
3. 方便數據庫的遷移。當需要遷移到新的數據庫時,不需要修改對象模型,只需要修改數據庫的配置。
ORM 的最令人詬病的地方就是性能問題,不過現在已經提高了很多,下面是 ORM 的幾個缺點
1. 性能問題
1. 自動化進行數據庫關系的映射需要消耗系統資源
2. 程序員編碼
3. 在處理多表聯查、where 條件復雜的查詢時,ORM 可能會生成的效率低下的 SQL
4. 通過 Lazy load 和 Cache 很大程度上改善了性能問題
2. SQL 調優,SQL 語句是由 ORM 框架自動生成,雖然減少了 SQL 語句錯誤的發生,但是也給 SQL 調優帶來了困難。
3. 越是功能強大的 ORM 越消耗內存,因為一個 ORM Object 會帶有很多成員變量和成員函數。
4. 對象和關系之間并不是完美映射
一般來說 ORM 足以滿足我們的需求,如果對性能要求特別高或者查詢十分復雜,可以考慮使用原生 SQL 和 ORM 共用的方式
使用原生sql優點:
1. 進行復雜的查詢時更加靈活
2. 可以根據需要編寫特殊的sql語句
使用原生sql缺點:
1. 需要對輸入進行嚴格的檢測
2. 自己寫的sql語句,很多時候使用的是字符串拼接,可能會有sql注入的漏洞
3. 不能使用django orm相關的一些特性
#### 簡述MVC和MTV
http://www.dongwm.com/archives/%E6%B5%85%E8%B0%88MVC%E3%80%81MTV%E5%92%8CMVVM/
#### django的contenttype組件的作用?
https://blog.csdn.net/Ayhan_huang/article/details/78626957
https://juejin.im/entry/581da04f128fe1005afdf618
#### 談談你對restfull 規范的認識?
http://www.ruanyifeng.com/blog/2014/05/restful_api.html
#### 接口的冪等性是什么意思?
https://www.jianshu.com/p/b09a2e9bcd29
#### 什么是RPC?
https://www.jianshu.com/p/2accc2840a1b
#### Http和Https的區別?
https://juejin.im/entry/58d7635e5c497d0057fae036
#### 為什么要使用django rest framework框架?
為什么要使用REST framework?
- 在線可視的API,對于贏得你的開發者們十分有用
驗證策略涵蓋了OAuth1a和OAuth2
同時支持ORM和非ORM數據源的序列化
可以配置各個環節,若無需更多強大的特性,使用一般基于方法(function-based)的視圖(views)即可
大量的文檔,強力的社區支持
大公司如同Mozilla和Eventbrite,也是忠實的使用者
#### django rest framework框架中都有那些組件?
#### django models中null和blank得區別
`null` 是針對數據庫而言,如果 `null=True`, 表示數據庫的該字段可以為空
`blank` 是針對表單的,如果 `blank=True`,表示你的表單填寫該字段的時候可以不填,比如 `admin` 界面下增加 `model` 一條記錄的時候。直觀的看到就是該字段不是粗體