超詳細的Django面試題

Hello,我是 Alex 007,爲啥是007呢?因爲叫 Alex 的人太多了,再加上每天007的生活,Alex 007就誕生了。

框架層

01.什麼是Django框架?(初級)

Django是一個開放源代碼的Web應用框架,由Python寫成。採用了MTV的框架模式。使用這種架構,程序員可以方便、快捷地創建高品質、易維護、數據庫驅動的應用程序。它還包含許多功能強大的第三方插件,使得Django具有較強的可擴展性。


02.Django對web開發有哪些優勢?(初級)

  • 功能完善、要素齊全:該有的、可以沒有的都有,自帶大量常用工具和框架,無須你自定義、組合、增刪及修改。

  • 完善的文檔:經過十多年的發展和完善,Django有廣泛的實踐案例和完善的在線文檔。開發者遇到問題時可以搜索在線文檔尋求解決方案。

  • 強大的數據庫訪問組件:Django的Model層自帶數據庫ORM組件,使得開發者無須學習其他數據庫訪問技術(SQL、pymysql、SQLALchemy等)。

  • 靈活的URL映射:Django使用正則表達式管理URL映射,靈活性高。新版的2.0,進一步提高了URL編寫的優雅性。

  • 豐富的Template模板語言:類似jinjia模板語言,不但原生功能豐富,還可以自定義模板標籤,並且與其ORM的用法非常相似。

  • 自帶後臺管理系統admin:只需要通過簡單的幾行配置和代碼就可以實現一個完整的後臺數據管理控制平臺。

  • 完整的錯誤信息提示:在開發調試過程中如果出現運行錯誤或者異常,Django可以提供非常完整的錯誤信息幫助定位問題。


03.簡述Django項目的組成模塊(初級)

Project:工程是承載了Django實例的所有設置的Python程序包。

大部分情況下,一個Web站點就是一個工程。工程內可以新建及存放該工程固有的應用,或者保存Web站點的設置(數據庫設置、Django的選項設置、各應用的設置等)

Apps:對於Django而言,應用之的是表示單一工程的Web應用的Python程序包。

由於其本質就是Python程序包,因此方法PYTHONPATH有效地任何位置都沒有問題。這裏最好儘量減少應用與工程、應用於應用之間的依賴關係,做到功能獨立,以便在其他工程中重複利用。

Model:Django提供了O/R映射工具,因此可以用Python代碼來描述數據庫佈局。

每個模型都是繼承了django.db.models.Model類的Python的類,分別對應數據庫中的一個表格。通過建數據庫的字段、關係、行爲定義爲模型類的屬性或方法,我們可以使用豐富且靈活的數據庫方位API。

URL Route:URL分配器機制使得URL信息不再受框架及擴展名的制約,從而讓Web應用的URL設計保持簡介。

URl在URlconf模塊中進行描述,URLconf模塊中包含使用正則表達式書寫的URL和Python函數的映像。URlconf能夠以應用爲單位進行分割,因此提高了應用的可重複利用性。另外,我們可以利用給URL設置名稱並定義的方式讓代碼和目標直接通過該名稱調用URL,從而將URL設計與代碼分離。

View:Django的視圖時一類函數,它能夠生成指定頁面的HttpResponse對象或像Http 404這樣的異常情況,返回HTTP請求。

典型的視圖函數的處理流程通常是從請求參數中獲取數據,讀取模型,熱按後根據獲取的數據渲染模板。

DTL:在Django的概念中,模板系統只負責顯示,並不是編寫邏輯代碼的環境。

因此Django的模板系統將設計與內容、代碼分離開來,是一共功能強、擴展性高、對設計者很友好的模板語言。

模板基於文本而不是XML,因此它不但能生成XML和HTML,還能生成E-mail、JavaScript、CSV等任意文本格式。

另外,如果使用模板繼承功能,子模板只需要將父模板中預留的空位填滿即可。我們在編寫模板時只需要描述各個模板獨有的部分,因此可以省去重複冗餘的編碼過程。

Admin:大多Web應用在運行過程中,都需要一個專供擁有管理員權限的用戶添加、編輯、刪除數據的界面,但是實際製作這個界面並不容易。

Django只需將已經完工的模型添加到管理站點,就能根據模型定義,動態地生成頁面。爲我們提供一個功能齊全的管理界面。

Cache System:Django可以使用memcached等緩存後端輕鬆地緩存數據。

比如可以將動態頁面的渲染結果緩存下來,等到下次需要時直接讀取緩存,從而不必每次都對動態頁面進行處理。

緩存的後端可以從memcached、數據庫、文件系統、本地內存等位置進行選擇。緩存對象也支持整個網站、特定的整個視圖、部分模板、特定數據等。


04.簡述MVC模式和MVT模式(初級)

在這裏插入圖片描述

MVC就是把Web應用分爲模型(M),控制器C和視圖(V)三層,他們之間以一種插件式的、鬆耦合的方式連接在一起,模型負責業務對象與數據庫的映射(ORM),視圖負責與用戶的交互(頁面),控制器接受用戶的輸入調用模型和視圖完成用戶的請求。

Django的MTV模式本質上和MVC是一樣的,也是爲了各組件間保持鬆耦合關係,只是定義上有些許不同,Django的MTV分別是:

M 代表模型(Model): 負責業務對象和數據庫的關係映射(ORM)。

T 代表模板 (Template):負責如何把頁面展示給用戶(html)。

V 代表視圖(View): 負責業務邏輯,並在適當時候調用Model和Template。

除了以上三層之外,還需要一個URL分發器,它的作用是將一個個URL的頁面請求分發給不同的View處理,View再調用相應的Model和Template,MTV的響應模式。


05.簡述Django請求生命週期(初級)

  1. uWSGI服務器通過wsgi協議,將HttpRequest交給web框架 (Flask、Django)

  2. 首先到達request中間件,對請求對象進行校驗或添加數據,例如:csrf、request.session,如果驗證不通過直接跳轉到response中間件

  3. 過URL配置文件找到urls.py文件

  4. 根據瀏覽器發送的URL,通過視圖中間件去匹配不同的視圖函數或視圖類,如果沒有找到相對應的視圖函數,就直接跳轉到response中間件

  5. 在視圖函數或視圖類中進行業務邏輯處理,處理完返回到response中間件

  6. 模型類通過ORM獲取數據庫數據,並返回序列化json或渲染好的Template到response中間件

  7. 所有最後離開的響應都會到達response中間件,對響應的數據進行處理,返回HttpResponse給wsgi

  8. wsgi經過uWSGI服務器,將響應的內容發送給瀏覽器。


07.什麼是WSGI?(初級)

WSGI(Web Server Gateway Interface,即Web服務器網關接口)是Python定義的Web服務器和Web應用程序或框架之間的一種簡單而通用的接口。

它是Python爲了解決Web服務器端與客戶端之間的通信問題而產生的,它基於現存的CGI標準而設計。

其定義了Web服務器如何與Python應用程序進行交互,讓Python寫的Web應用程序可以和Web服務器對接起來。


08.uwsgi、uWSGI和WSGI的區別?(中級)

  • uwsgi:是uWSGI服務器實現的獨有協議,用於Nginx服務與uWSGI服務的通信規範

  • uWSGI:是一個Web服務器,它實現了WSGI/uwsgi/HTTP等協議,用於接收Nginx轉發的動態請求,處理後發個python應用程序

  • WSGI:用在python web框架(Django/Flask)編寫的應用程序與web服務器之間的規範


09.Django的HttpRequest對象是在什麼時候創建的?(中級)

class WSGIHandler(base.BaseHandler):
    request = self.request_class(environ)

請求走到WSGIHandler類的時候,執行cell方法,將environ封裝成了request。


10.什麼是中間件並簡述其作用(初級)

中間件是一個用來處理Django請求和響應的框架級鉤子。

它是一個輕量、低級別的插件系統,用於在全局範圍內改變Django的輸入和輸出。

每個中間件組件都負責做一些特定的功能。


11.列舉django中間件的5個方法,以及django中間件的應用場景(初級)

process_request : 請求進來時,權限認證

process_view : 路由匹配之後,能夠得到視圖函數

process_exception : 異常時執行

process_template_responseprocess : 模板渲染時執行

process_response : 請求有響應時執行


12.簡述Django對http請求的執行流程(初級)

在接受一個Http請求之前的準備,需啓動一個支持WSGI網關協議的服務器監聽端口等待外界的Http請求,比如Django自帶的開發者服務器或者uWSGI服務器。

Django服務器根據WSGI協議指定相應的Handler來處理Http請求。

此時服務器已處於監聽狀態,可以接受外界的Http請求,當一個http請求到達服務器的時候,Django服務器根據WSGI協議從Http請求中提取出必要的參數組成一個字典(environ)並傳入Handler中進行處理。

在Handler中對已經符合WSGI協議標準規定的http請求進行分析,比如加載Django提供的中間件,路由分配,調用路由匹配的視圖等。

最後返回一個可以被瀏覽器解析的符合Http協議的HttpResponse。


13.Django中session的運行機制是什麼?(初級)

django的session存儲可以利用中間件來實現。

需要在 settings.py 文件中註冊APP、設置中間件用於啓動。

設置存儲模式(數據庫/緩存/混合存儲)和配置數據庫緩存用於存儲,生成django_session表單用於讀寫。


14. 什麼是CSRF,請描述其攻擊原理,在Django中如何解決?(初級)

CSRF(cross-site request forgery)簡稱跨站請求僞造。

例如,你訪問了信任網站A,然後網站A會用保存你的個人信息並返回給你的瀏覽器一個cookie。
然後呢,在cookie的過期時間之內,你去訪問了惡意網站B,它給你返回一些惡意請求代碼,要求你去訪問網站A。
而你的瀏覽器在收到這個惡意請求之後,在你不知情的情況下,會帶上保存在本地瀏覽器的cookie信息去訪問網站A,然後網站A誤以爲是用戶本身的操作。
這將導致來自惡意網站C的攻擊代碼會被執行:發郵件,發消息,修改你的密碼,購物,轉賬,偷窺你的個人信息,導致私人信息泄漏和賬戶財產安全受到威脅。

在post請求時,form表單或ajax裏添加csrf_token,服務端開啓CSRF中間件進行驗證。

解決原理是頁面添加csrf_token值後,用戶通過URL訪問(GET請求)該頁面時,Django會在響應中自動幫我們生成cookie信息,返回給瀏覽器,同時在前端代碼會生成一個csrf_token值。

然後當你POST提交信息時,Django會自動比對cookie裏和前端form表單或ajax提交上來的csrf_token值,兩者一致,說明是當前瀏覽器發起的正常請求並處理業務邏輯返回響應。

那麼第三方網站拿到你的cookie值爲什麼不能通過驗證呢?

因爲他沒你前端的那個隨機生成的token值,他總不能跑到你電腦面前查看你的瀏覽器前端頁面自動隨機生成的token值吧。


15. Django中CSRF的實現機制(初級)

  1. django第1次響應來自某個客戶端的請求時,服務器隨機產生1個token值,把這個token保存在session中;同時服務器把這個token放到cookie中交給前端頁面;

  2. 該客戶端再次發起請求時,把這個token值加入到請求數據或者頭信息中,一起傳給服務器;

  3. 服務器校驗前端請求帶過來的token和session裏的token是否一致。


16.什麼是跨域請求,其有哪些方式?(初級)

  • 跨域是指一個域下的文檔或腳本試圖去請求另一個域下的資源。

方式如下:

  1. 資源跳轉: a鏈接、重定向、表單提交

  2. 資源嵌入: link/script/img/frame/dom等標籤,還有樣式中background:url()、@font-face()等文件外鏈

  3. 腳本請求: js發起的ajax請求、dom和js對象的跨域操作等


17.跨域請求Django是如何處理的?(初級)

使用第三方工具 django-cors-headers 即可徹底解決

  • 註冊app

  • 添加中間件

  • 配置運行跨域請求方法


16.什麼是信號量?(初級)

Django包含一個"信號調度程序",它有助於在框架中的其他位置發生操作時通知分離的應用程序。

簡而言之,信號允許某些發送者通知一組接收器已經發生了某些動作。

當許多代碼可能對同一事件感興趣時,它們特別有用。


17.web框架的本質是什麼?(初級)

web框架本質是一個socket服務端,用戶的瀏覽器是一個socket客戶端。


18.談談你對restful規範的認識(初級)

restful是一種軟件架構設計風格,並不是標準,它只是提供了一組設計原則和約束條件,主要用於客戶端和服務器交互類的軟件。

就像設計模式一樣,並不是一定要遵循這些原則,而是基於這個風格設計的軟件可以更簡潔,更有層次,我們可以根據開發的實際情況,做相應的改變。

它裏面提到了一些規範,例如

1.restful 提倡面向資源編程,在url接口中儘量要使用名詞,不要使用動詞

2.在url接口中推薦使用Https協議,讓網絡接口更加安全

3.可以根據Http不同的method,進行不同的資源操作

4.在url中可以體現版本號

5.url中可以體現是否是API接口

6.url中可以添加條件去篩選匹配

7.響應式應該設置狀態碼

8.有返回值,而且格式爲統一的json格式

9.返回錯誤信息

10.返回結果中要提供幫助鏈接,即API最好做到Hypermedia


19.Django中如何加載初始化數據?(初級)

Django在創建對象時在調用save()方法後,ORM框架會把對象的屬性寫入到數據庫中,實現對數據庫的初始化。

通過操作對象,查詢數據庫,將查詢集返回給視圖函數,通過模板語言展現在前端頁面。


20.Django緩存系統類型有哪些?(初級)

  1. 全站緩存,較少使用
MIDDLEWARE_CLASSES = (
    ‘django.middleware.cache.UpdateCacheMiddleware’,  # 第一
    'django.middleware.common.CommonMiddleware',
    ‘django.middleware.cache.FetchFromCacheMiddleware’,  # 最後
)
  1. 視圖緩存,用戶視圖函數或視圖類中
from django.views.decorators.cache import cache_page
import time

@cache_page(15) #超時時間爲15秒
def index(request):
    t=time.time() #獲取當前時間
    return render(request,"index.html",locals())
  1. 模板緩存,指緩存不經常變換的模板片段
{% load cache %}
    <h3 style="color: green">不緩存:-----{{ t }}</h3>

{% cache 2 'name' %} # 存的key
    <h3>緩存:-----:{{ t }}</h3>
{% endcache %}


21.請簡述Django下的(內建)緩存機制(初級)

Django根據設置的緩存方式,瀏覽器第一次請求時,cache會緩存單個變量或整個網頁等內容到硬盤或者內存中,同時設置response頭部。

當瀏覽器再次發起請求時,附帶f-Modified-Since請求時間到Django。

Django發現f-Modified-Since會先去參數之後,會與緩存中的過期時間相比較,如果緩存時間比較新,則會重新請求數據,並緩存起來然後返回response給客戶端。

如果緩存沒有過期,則直接從緩存中提取數據,返回給response給客戶端。


22.什麼是ASGI,簡述WSGI和ASGI的關係與區別?(初級)

ASGI是異步網關協議接口,一個介於網絡協議服務和Python應用之間的標準接口,能夠處理多種通用的協議類型,包括HTTP,HTTP2和WebSocket。

WSGI是基於HTTP協議模式的,不支持WebSocket,而ASGI的誕生則是爲了解決Python常用的WSGI不支持當前Web開發中的一些新的協議標準。

同時,ASGI對於WSGI原有的模式的支持和WebSocket的擴展,即ASGI是WSGI的擴展。


23.Django如何實現websocket?(初級)

django實現websocket使用channels。

channels通過http協議升級到websocket協議,保證實時通訊。

也就是說,我們完全可以用channels實現我們的即時通訊,而不是使用長輪詢和計時器方式來保證僞實時通訊。

他使用asgi協議而不是wsgi協議,他通過改造django框架,使django既支持http協議又支持websocket協議。


25.列舉django的核心組件(初級)

  • 用於創建模型的對象關係映射;

  • 爲最終用戶設計較好的管理界面;

  • URL設計;

  • 設計者友好的模板語言;

  • 緩存系統。


26.Django本身提供了runserver,爲什麼不能用來部署?(初級)

  1. runserver方法是調試 Django 時經常用到的運行方式,它使用Django自帶的WSGI Server 運行,主要在測試和開發中使用,並且 runserver 開啓的方式也是單進程。

  2. uWSGI是一個Web服務器,它實現了WSGI協議、uwsgi、http 等協議。

注意uwsgi是一種通信協議,而uWSGI是實現uwsgi協議和WSGI協議的 Web 服務器。

uWSGI具有超快的性能、低內存佔用和多app管理等優點,並且搭配着Nginx就是一個生產環境了,能夠將用戶訪問請求與應用 app 隔離開,實現真正的部署。

相比來講,支持的併發量更高,方便管理多進程,發揮多核的優勢,提升性能。


27.ajax請求的csrf解決方法(高級)

  1. 首先在你需要發起ajax post請求的頁面的裏面隨便一個地方加上 {% crsr_token %}

  2. 在發起ajax post 請求時,組織json參數時,將瀏覽器cookie中的值賦予加入json中,鍵名爲‘csrfmiddlewaretoken’


路由層

01.路由優先匹配原則是什麼?(初級)

在url匹配列表中位置優先匹配

如第1條和第2條同時滿足匹配規則,則優先匹配第1條。

如第1條爲正則模糊匹配,第2條爲精確匹配,也是優先匹配第1條

02.urlpatterns中的name與namespace的區別(初級)

name:給路由起一個別名

namespace:防止多個應用之間的路由重複


03.Django路由系統中include是幹嘛用的?(初級)

include用作路由轉發,通常,我們會在每個app裏,各自創建一個urls.py路由模塊,然後從根路由出發,將app所屬的url請求,全部轉發到相應的urls.py模塊中。


04.Django2.x中的path與django1.x裏面的URL有什麼區別?(初級)

path與url是兩個不同的模塊,效果都是響應返回頁面, path調用的是python第三方模塊或框架,而url則是自定義的模塊。

url默認支持正則表達式,而path不支持,正則表達式需要使用另外一個函數re_path。


05.Django重定向的幾種方法,用的什麼狀態碼?(初級)

  • HttpResponse

  • Redirect

  • Reverse

狀態碼:302,301


模型層

01.命令migrate 和makemigrations的差別?(初級)

  • makemigrations:生成遷移文件

  • migrate:執行遷移


02.Django的Model的繼承有幾種形式?(初級)

  1. 抽象繼承

父類繼承來自model.Model, 但不會在底層數據庫生成相應的數據表,父類的屬性存儲在其子類的數據表中。

作用:多個表若有相同的字段時,可以將這些字段統一定義在抽象類中.

對於內聯的Meta類的繼承,一般的,父類的Meta類的屬性會繼承給子類,子類也可以在自己的Meta中重寫或者拓展父類的Meta,拓展的話主要是繼承父類的Meta。

  1. 多表繼承

每個模型類都會在底層數據庫中生成相應的數據表管理數據。

父類中的字段不會重複地在對個子類相關的數據表中進行定義。

  1. proxy model(代理model)

代理模型中子類只用於管理父類的數據,而不實際存儲數據。

使用原因:子類中的新特性不會影響父類行爲以及已有代碼的行爲。


03.class Meta中的元信息字段有哪些?(初級)

  1. Model類可以通過元信息類設置索引和排序信息

  2. 元信息是在Model類中定義一個Meta子類

class Meta:
    # ---常用
    db_table = 'table_name'             # 自定義表名
    index_together = ('tag1', 'tag2')   # 聯合索引
    unique_together = ('tag3', 'tag4')  # 聯合唯一索引
    verbose_name = 'table_name'         # /admin/中顯示的表名稱
    verbose_name_plural = verbose_name 
    ordering = 'ordering_tag'           # 排序字段#這個選項是指定,模型的複數形式是什麼
    abstract =True                      # 抽象基類
    
    # ---非常用
    # app_label這個選項只在一種情況下使用,就是你的模型類不在默認的應用程序包下的models.py文件中,
    # 這時候你需要指定你這個模型類是那個應用程序的。
    # 比如你在其他地方寫了一個模型類,而這個模型類是屬於myapp的
    app_label='myapp'  
    
    # db_table 是用於指定自定義數據庫表名的。
    db_table='my_owner_table' 
    
    # 有些數據庫有數據庫表空間,比如Oracle。你可以通過db_tablespace來
    # 指定這個模型對應的數據庫表放在哪個數據庫表空間。
    db_tablespace
    
    # 由於Django的管理方法中有個lastest()方法,就是得到最近一行記錄。
    # 如果你的數據模型中有 DateField 或 DateTimeField 類型的字段,
    # 你可以通過這個選項來指定lastest()是按照哪個字段進行選取的
    get_latest_by = "order_date"
    
    # 由於Django會自動根據模型類生成映射的數據庫表,如果你不希望Django這麼做,可以把managed的值設置
    # 爲False。默認值爲True,這個選項爲True時Django可以對數據庫表進行 migrate或migrations、
    # 刪除等操作。在這個時間Django將管理數據庫中表的生命週期如果爲False的時候,不會對數據庫表進行
    # 創建、刪除等操作。可以用於現有表、數據庫視圖等,其他操作是一樣的。
    managed
    
    # permissions主要是爲了在Django Admin管理模塊下使用的,如果你設置了這個屬性可以讓
    # 指定的方法權限描述更清晰可讀。要創建一個對象所需要的額外的權限. 如果一個對象有 admin 設置,
    # 則每個對象的添加,刪除和改變權限會人(依據該選項)自動創建.
    # 下面這個例子指定了一個附加權限: can_deliver_pizzas:
    permissions = (("can_deliver_pizzas", "Can deliver pizzas"),)
    
    # 這個選項一般用於多對多的關係中,它指向一個關聯對象。就是說關聯對象找到這個對象後它是經過排序的。
    # 指定這個屬性後你會得到一個get_XXX_order()和set_XXX_order()的方法,
    # 通過它們你可以設置或者回去排序的對象。
    order_with_respect_to = 'pizza'

04.Django模型類關係有哪幾種?(初級)

  • 一對一關係:OneToOneField

  • 一對多關係:ForeignKey

  • 多對多關係:ManyToManyField


05.外鍵有什麼用,什麼時候合適使用外鍵 ,外鍵一定需要索引嗎?(中級)

  • 程序很難100%保證數據的完整性,而用外鍵即使在數據庫服務器宕機或異常的時候,也能夠最大限度的保證數據的一致性和完整性。

  • 如果項目性能要求不高,安全要求高,建議使用外鍵,如果項目性能要求高,安全自己控制,不用外鍵,因爲外鍵查詢比較慢。

  • 加入外鍵的主要問題就是影響性能,因此加入索引能加快關聯查詢的速度。


06.Primary KeyUnique Key的區別?(中級)

  • Primary key與Unique Key都是唯一性約束。

  • Primary key是主鍵,一個表只能由一個,Unique key是唯一鍵,一個表可以有多個唯一鍵字段。

  • Primary key 必須不能爲空,Unique Key 可爲空。


07.DateTimeField類型中的auto_nowauto_now_add有什麼區別?(初級)

  • DateTimeField.auto_now 用於記錄更新時間

這個參數的默認值爲false,設置爲true時,能夠在保存該字段時,將其值設置爲當前時間,並且每次修改model,都會自動更新。

因此這個參數在需要存儲“最後修改時間”的場景下,十分方便。

需要注意的是,設置該參數爲true時,並不簡單地意味着字段的默認值爲當前時間,而是指字段會被“強制”更新到當前時間,你無法程序中手動爲字段賦值。

如果使用django再帶的admin管理器,那麼該字段在admin中是隻讀的。

  • DateTimeField.auto_now_add 用於記錄創建時間

這個參數的默認值也爲False,設置爲True時,會在model對象第一次被創建時,將字段的值設置爲創建時的時間,以後修改對象時,字段的值不會再更新。

該屬性通常被用在存儲“創建時間”的場景下。

與auto_now類似,auto_now_add也具有強制性,一旦被設置爲True,就無法在程序中手動爲字段賦值,在admin中字段也會成爲只讀的。


08.當刪除一個外鍵的時候,其關聯的表有幾種處理方式?(初級)

有6種處理方式:

  1. 同時刪除父表和子表

CASCADE:代表刪除聯級,父表(少類表)被刪除的記錄在子表(多類表)中所有字段也會被對應刪除,模擬SQL語言中的ON DELETE CASCADE約束,將定義有外鍵的模型對象同時刪除!(該操作爲當前Django版本的默認操作!)

  1. 阻止刪除父表

PROTECT:阻止上面的刪除操作,但是彈出ProtectedError異常

  1. 子表設置爲空

SET_NULL:代表父表(少類表)被刪除後子表(多類表)對應的外鍵字段會設置爲null,只有當字段設置了null=True,blank=True時,方可使用該值。

  1. 子表設置爲默認值

SET_DEFAULT:代表父表(少類表)被刪除後子表(多類表)對應的外鍵字段會設置爲默認值。只有當字段設置了default參數時,方可使用。

  1. 子表什麼都不做

DO_NOTHING:什麼也不做,一切看數據庫級別的約束

  1. 設置爲一個傳遞給SET()的值或者一個回調函數的返回值

SET():設置爲一個傳遞給SET()的值或者一個回調函數的返回值。注意大小寫,用得很少。


09.如何通過外鍵,子表查詢父表和父表查詢子表(中級)

父表和子表關係如下:

from django.db import models
 
class Person(models.Model):
    name = models.CharField(max_length=64)
    age = models.IntegerField()
    tel = models.CharField(max_length=64)
 
    @property
    def all_cars(self):
        '''返回全部信息'''
        return self.cars.all()
 
    @property
    def info(self):
        '''返回部分信息'''
        return '%s %s' % (self.name, self.tel)
 
class Car(models.Model):
    owner = models.Foreignkey(Person, related_name='cars')
    name = models.CharField(max_length=64)
    price = models.FloatField()

子表查詢父表

car = Car.objects.get(id=1)
# 查詢該車的車主
owner = car.owner

父表查詢子表

Tom = Person.objects.get(id=1)
# 查詢此人有多少車
# 方式一:
# Django默認每個主表對象都有一個外鍵的屬性,可以通過它來查詢所有屬於主表的子表信息
# 查詢方式:主表.子表_set(),返回值爲一個queryset對象
Tom.Car_set().all()
# 方式二:
# 通過在外鍵中設置related_name屬性值既可
Tom.cars.all()
# 方式三:
# 通過@property裝飾器在model中預定義方法實現
Tom.all_cars

10.談談 GenericForeignkey 和 GenericRelation(高級)

GenericForeignkey 和 GenericRelation 的方法能夠解決多外鍵的表單產生的大量沉餘數據。

通過ContentType的查詢,起到一個自動一對多的作用,能和任何模型都能連接起來,保證了代碼的乾淨。

避免了創建大量無用的空數據,有效減少存儲空間和服務器壓力。


11.django中怎麼寫原生SQL?(中級)

  1. 使用extra
# 查詢人民郵電出版社出版並且價格大於50元的書籍
Book.objects.filter(publisher__name='人民郵電出版社').extra(where=['price>50']) 
  1. 使用raw
books=Book.objects.raw('select * from hello_book')  

for book in books:  
   print(book)
  1. 使用遊標
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() 

12.談一談你對ORM的理解(中級)

ORM是“對象-關係-映射”的簡稱。

ORM是MVC或者MVC框架中包括一個重要的部分,它實現了數據模型與數據庫的解耦,即數據模型的設計不需要依賴於特定的數據庫,通過簡單的配置就可以輕鬆更換數據庫,這極大的減輕了開發人員的工作量,不需要面對因數據庫變更而導致的無效勞動。


13.如何使用Django ORM批量創建數據?(初級)

可以使用django.db.models.query.QuerySet.bulk_create()批量創建對象,減少SQL查詢次數。

# 創建一個空列表
querysetlist=[]

# 把創建的對象添加入列表中
for i in resultlist:
    querysetlist.append(Account(name=i))   
    
# 批量創建
Account.objects.bulk_create(querysetlist)

14.列舉django ORM中操作QuerySet對象的方法(至少5個)(初級)

方法 作用
all() 查詢所有結果
filter() 過濾查詢對象。獲取不到返回None。
get() 返回與所給篩選條件相匹配的對象,返回結果有且只有1個。如果符合篩選條件的對象超過1個或者沒有都會拋出錯誤。
exclude() 排除滿足條件的對象
order_by() 對查詢結果排序
reverse() 對查詢結果反向排序
count() 返回數據庫中匹配查詢(QuerySet)的對象數量。
first() 返回第一條記錄
last() 返回最後一條記錄
exists() 如果QuerySet包含數據,就返回True,否則返回False
values() 返回包含對象具體值的字典的QuerySet
values_list() 與values()類似,只是返回的是元組而不是字典。
distinct() 對查詢集去重

15.ORM如何取消級聯?(初級)

user = models.ForeignKey(User,blank=True,null=True,on_delete=models.SET_NULL)

在父表被刪除,null爲True的時候就會取消級聯。


16.查詢集的2大特性?什麼是惰性執行?(中級)

特性:

  1. 惰性執行

  2. 緩存

惰性執行是指創建查詢集不會訪問數據庫,直到調用數據時,纔會訪問數據庫。


17.查詢集返回的列表過濾器有哪些?(中級)

all():返回所有數據

filter():返回滿足條件的數據

exclude():返回滿足條件之外的數據,相當於sql語句中where部分的not關鍵字

order_by():排序


18.selected_related與prefetch_related有什麼區別?(高級)

在Django中當創建一個查詢集的時候,並沒有跟數據庫發生任何交互。

因此我們可以對查詢集進行級聯的filter等操作,只有在訪問Queryset的內容的時候,Django纔會真正進行數據庫的訪問。

而多頻率、複雜的數據庫查詢往往是性能問題最大的根源。

不過我們實際開發中,往往需要訪問到外鍵對象的其他屬性。

如果按照默認的查詢方式去遍歷取值,那麼會造成多次的數據庫查詢,效率可想而知。

在查詢對象集合的時候,把指定的外鍵對象也一併完整查詢加載,避免後續的重複查詢。

使用 select_related() 和 prefetch_related() 可以很好的減少數據庫請求的次數,從而提高性能。

  • select_related適用於一對一字段(OneToOneField)和外鍵字段(ForeignKey)查詢;

  • prefetch_related適用多對多字段(ManyToManyField)和一對多字段的查詢。


19.values()與values_list()有什麼區別?(初級)

values : 讀取字典的Queryset

values_list : 讀取元組的Queryset


20.QueryDict和dict區別?(高級)

在HttpRequest對象中, GET和POST屬性是django.http.QueryDict類的實例。

QueryDict類似字典的自定義類,用來處理單鍵對應多值的情況。

在 HttpRequest 對象中,屬性 GET 和 POST 得到的都是 django.http.QueryDict 所創建的實例。

這是一個django 自定義的類似字典的類,用來處理同一個鍵帶多個值的情況。

在 python 原始的字典中,當一個鍵出現多個值的時候會發生衝突,只保留最後一個值。

而在 HTML 表單中,通常會發生一個鍵有多個值的情況,例如,多選框就是一個很常見情況。

request.POST 和request.GET 的QueryDict 在一個正常的請求/響應循環中是不可變的。

若要獲得可變的版本,需要使用.copy()方法。

  • python dict當一個鍵出現多個值的時候會發生衝突,只保留最後一個值。

  • QueryDict是類似字典的自定義類,用來處理單鍵對應多值的情況。


21.Django中查詢Q和F的區別?(中級)

Q查詢:對數據的多個字段聯合查詢(常和且或非"& | ~"進行聯合使用)

F查詢:對數據的不同字段進行比較(常用於比較和更新,對數據進行加減操作)


視圖層

01.簡述什麼是FBV和CBV(初級)

FBV(function base views)使用視圖函數處理請求

CBV(class base views)使用視圖類處理請求


02.如何給CBV的程序添加裝飾器?(初級)

導入 method_decorator 裝飾器

  1. 給方法加

  2. 給dispatch加

  3. 給類加

from django.utils.decorators import method_decorator


@method_decorator(check_login)
def post(self, request):
    '''給方法加'''
    ...
    
@method_decorator(check_login)
def dispatch(self, request, *args, **kwargs):
    '''給dispatch加'''
    ...
    
@method_decorator(check_login, name="get")
@method_decorator(check_login, name="post")
class HomeView(View):
    '''給類加'''
    ...


03.常用視圖響應的方式有哪些?(初級)

常用視圖響應的方式有4種方式redirect、Response、HttpResponse和JsonResponse

return Response(content=響應體, content_type=響應體數據類型, status=狀態碼)
return HttpResponse(content=響應體, content_type=響應體數據類型, status=狀態碼) 
return JsonResponse({‘city’: ‘beijing’, ‘subject’: ‘python’},status=response.status_code)
return redirect(/index.html’)

04.在視圖函數中,常用的驗證裝飾器有哪些?(中級)

裝飾器 用途
@login_required() 檢查用戶是否通過身份驗證
@group_required() 檢查用戶是否屬於有權限的用戶組訪問
@anonymous_required() 檢驗用戶是否已經登錄
@superuser_only() 它只允許超級用戶才能訪問視圖
@ajax_required 用於檢查請求是否是AJAX請求
@timeit 用於改進某個視圖的響應時間,或者只想知道運行需要多長時間

05.視圖函數和視圖類的區別?(高級)

優點 缺點
視圖函數 容易實現跟理解;流程簡單;直接使用裝飾器 代碼難以重用;處理HTTP請求時要有分支表達式
視圖類 易拓展跟代碼重用;可以用混合類繼承;單獨用類方法處理HTTP請求;有許多內置的通用視圖函數 不容易去理解;代碼流程負載;父類混合類中隱藏較多代碼;使用裝飾器時需要額外的導入或覆蓋方法

高階

01.Django如何實現高併發?(高級)

  • Nginx + uWSGI + Django

  • Nginx + gunicorn + gevent + Django


02.如何提高Django應用程序的性能?(高級)

  • 前端優化

1.減少 http 請求,減少數據庫的訪問量,比如使用雪碧圖。

2.使用瀏覽器緩存,將一些常用的 css,js,logo 圖標,這些靜態資源緩存到本地瀏覽器,通過設置 http 頭中的 cache-control 和 expires 的屬性,可設定瀏覽器緩存,緩存時間可以自定義。

3.對 html,css,javascript 文件進行壓縮,減少網絡的通信量。

  • 後端優化

1.合理的使用緩存技術,對一些常用到的動態數據,比如首頁做一個緩存,或者某些常用的數據做個緩存,設置一定得過期時間,這樣減少了對數據庫的壓力,提升網站性能。

2.使用 celery 消息隊列,將耗時的操作扔到隊列裏,讓 worker 去監聽隊列裏的任務,實現異步操作,比如發郵件,發短信。

3.就是代碼上的一些優化,補充:nginx 部署項目也是項目優化,可以配置合適的配置參數,提升效率,增加併發量。

4.如果太多考慮安全因素,服務器磁盤用固態硬盤讀寫,遠遠大於機械硬盤,這個技術現在沒有普及,主要是固態硬盤技術上還不是完全成熟, 相信以後會大量普及。

5.服務器橫向擴展。


03.Django中當用戶登錄到A服務器進入登陸狀態,下次被nginx代理到B服務器會出現什麼影響?(高級)

如果用戶在A應用服務器登陸的session數據沒有共享到B應用服務器,那麼之前的登錄狀態就沒有了。


04.談談對Celery的理解(高級)

Celery是由Python開發、簡單、靈活、可靠的分佈式任務隊列,其本質是生產者消費者模型,生產者發送任務到消息隊列,消費者負責處理任務。

Celery側重於實時操作,但對調度支持也很好,其每天可以處理數以百萬計的任務。

特點:

簡單:熟悉celery的工作流程後,配置使用簡單

高可用:當任務執行失敗或執行過程中發生連接中斷,celery會自動嘗試重新執行任務

快速:一個單進程的celery每分鐘可處理上百萬個任務

靈活:幾乎celery的各個組件都可以被擴展及自定製

05.Celery有哪些應用場景?(高級)

  1. 異步任務:當用戶在網站進行某個操作需要很長時間完成時,我們可以將這種操作交給Celery執行,直接返回給用戶,等到Celery執行完成以後通知用戶,大大提好網站的併發以及用戶的體驗感。例如:發送驗證郵件

  2. 定時任務:向定時清除沉餘數據或批量在幾百臺機器執行某些命令或者任務,此時Celery可以輕鬆搞定。


06.Celery的工作原理是什麼?(高級)

Celery由以下三部分構成:消息中間件(Broker)、任務執行單元Worker、結果存儲(Backend),如下圖:

在這裏插入圖片描述
工作原理:

任務模塊Task包含異步任務和定時任務。

其中,異步任務通常在業務邏輯中被觸發併發往消息隊列,而定時任務由Celery Beat進程週期性地將任務發往消息隊列;

任務執行單元Worker實時監視消息隊列獲取隊列中的任務執行;

Woker執行完任務後將結果保存在Backend中;

消息中間件Broker

消息中間件Broker官方提供了很多備選方案,支持RabbitMQ、Redis、Amazon SQS、MongoDB、Memcached 等,官方推薦RabbitMQ。

任務執行單元Worker

Worker是任務執行單元,負責從消息隊列中取出任務執行,它可以啓動一個或者多個,也可以啓動在不同的機器節點,這就是其實現分佈式的核心。

結果存儲Backend

Backend結果存儲官方也提供了諸多的存儲方式支持:RabbitMQ、 Redis、Memcached,SQLAlchemy, Django ORM、Apache Cassandra、Elasticsearch。

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章