深入解析 Django REST Framework 的 APIView 核心方法

在 Python 3 中,Django 的 APIView 類是 Django REST Framework(DRF)中用于構建 API 視圖的核心基類。它提供了一個靈活的框架來處理 HTTP 請求,并通過一系列方法支持認證、權限檢查和請求限制等功能。

在這里插入圖片描述

  • self.perform_authentication(request):認證
  • self.check_permissions(request) :權限驗證
  • self.check_throttles(request) :請求速率限制

1. self.perform_authentication(request)

作用

self.perform_authentication(request) 用于對傳入的 HTTP 請求進行身份認證(authentication)。它的主要目的是驗證請求是否來自合法用戶,并將認證后的用戶信息(如用戶對象)綁定到 request.userrequest.auth 屬性上。

  • request.user: 通常存儲認證后的用戶對象(例如 Django 的 User 模型實例)。如果未認證,默認為 AnonymousUser
  • request.auth: 存儲認證過程中可能附加的認證信息,例如 JWT 令牌、OAuth 令牌等。
實現原理

perform_authentication 方法調用了 DRF 的認證流程,依賴于 authentication_classes 屬性中定義的認證類。DRF 的認證機制是模塊化的,允許開發者通過配置不同的認證類(如 SessionAuthenticationTokenAuthenticationJWTAuthentication 等)來支持多種認證方式。

APIView 類中,perform_authentication 的定義如下(參考 DRF 源碼,基于 3.15 版本):

def perform_authentication(self, request):request.user

看似簡單,但實際邏輯隱藏在 request.user 的屬性訪問中。當訪問 request.user 時,DRF 會觸發以下步驟:

  1. 獲取認證類:從 self.authentication_classes 獲取配置的認證類列表。這些類繼承自 rest_framework.authentication.BaseAuthentication
  2. 逐個調用認證類:按順序調用每個認證類的 authenticate 方法,嘗試對請求進行認證。
    • 每個 authenticate 方法返回一個 (user, auth) 元組,表示認證成功;如果返回 None,則嘗試下一個認證類。
    • 如果認證失敗且認證類拋出 AuthenticationFailed 異常,DRF 會立即返回 401 Unauthorized 響應。
  3. 設置認證結果
    • 如果認證成功,request.user 被設置為認證后的用戶對象,request.auth 被設置為認證令牌或其他上下文信息。
    • 如果沒有認證類成功認證,request.user 默認為 AnonymousUserrequest.authNone
執行時機

perform_authenticationAPIViewinitial 方法中被調用,initial 方法是請求處理流程的初始化階段:

def initial(self, request, *args, **kwargs):self.perform_authentication(request)self.check_permissions(request)self.check_throttles(request)# 其他初始化邏輯
配置認證類

APIView 子類中,可以通過 authentication_classes 屬性指定認證方式。例如:

from rest_framework.views import APIView
from rest_framework.authentication import SessionAuthentication, TokenAuthenticationclass MyAPIView(APIView):authentication_classes = [SessionAuthentication, TokenAuthentication]def get(self, request):return Response({"user": request.user.username})

在上述例子中,DRF 會優先嘗試 SessionAuthentication,如果失敗則嘗試 TokenAuthentication

注意事項
  • 短路行為perform_authentication 不會直接拋出異常,而是依賴認證類的實現。如果所有認證類都返回 None,請求被視為匿名請求。
  • 性能考慮:認證可能涉及數據庫查詢(如驗證用戶令牌),因此應盡量優化認證類的實現,避免不必要的性能開銷。
  • 自定義認證:可以繼承 BaseAuthentication 創建自定義認證類,并添加到 authentication_classes 中。例如:
from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailedclass CustomAuth(BaseAuthentication):def authenticate(self, request):auth_header = request.headers.get('Authorization')if not auth_header:return None# 自定義認證邏輯user = validate_token(auth_header)  # 假設的 token 驗證函數if not user:raise AuthenticationFailed('Invalid token')return (user, auth_header)
常見使用場景
  • 基于令牌的認證:如 TokenAuthentication 或 JWT,用于移動端或單頁應用。
  • 會話認證:如 SessionAuthentication,適用于基于瀏覽器的應用。
  • 匿名訪問:允許匿名用戶訪問某些 API(request.userAnonymousUser)。

2. self.check_permissions(request)

作用

self.check_permissions(request) 用于檢查請求用戶是否具有執行當前操作的權限。它基于 permission_classes 屬性中定義的權限類,決定是否允許請求繼續處理。如果權限檢查失敗,DRF 會拋出 PermissionDenied 異常,導致返回 403 Forbidden 響應。

實現原理

check_permissions 方法會遍歷 self.permission_classes 中定義的權限類,調用每個權限類的 has_permission 方法:

def check_permissions(self, request):for permission in self.get_permissions():if not permission.has_permission(request, self):self.permission_denied(request, message=getattr(permission, 'message', None))
  • 權限類:每個權限類繼承自 rest_framework.permissions.BasePermission,并實現 has_permission 方法(對于對象級權限,還可能實現 has_object_permission)。
  • 檢查邏輯has_permission 方法返回 True 表示權限通過,False 表示拒絕。如果任何一個權限類返回 False,DRF 會拋出 PermissionDenied 異常。
  • 錯誤處理permission_denied 方法會生成 403 響應,并包含權限類提供的錯誤信息(如果有)。
執行時機

check_permissionsinitial 方法中,在 perform_authentication 之后調用。這是因為權限檢查通常依賴于認證結果(例如,檢查 request.user 是否有特定權限)。

配置權限類

可以通過 permission_classes 屬性指定權限。例如:

from rest_framework.views import APIView
from rest_framework.permissions import IsAuthenticated, IsAdminUserclass MyAPIView(APIView):permission_classes = [IsAuthenticated, IsAdminUser]def get(self, request):return Response({"message": "You have admin access"})

在上述例子中,用戶必須同時通過 IsAuthenticated(已登錄)和 IsAdminUser(管理員權限)檢查才能訪問 API。

內置權限類

DRF 提供了一些常用的權限類:

  • AllowAny: 允許所有用戶(包括匿名用戶)訪問。
  • IsAuthenticated: 僅允許已認證用戶訪問。
  • IsAdminUser: 僅允許管理員用戶訪問。
  • IsAuthenticatedOrReadOnly: 允許匿名用戶的只讀訪問(GET、HEAD、OPTIONS),但寫操作需要認證。
自定義權限

可以創建自定義權限類。例如,限制只有特定角色的用戶可以訪問:

from rest_framework.permissions import BasePermissionclass IsPremiumUser(BasePermission):def has_permission(self, request, view):return request.user.is_authenticated and request.user.is_premium
注意事項
  • 權限順序:權限類按順序檢查,建議將更嚴格的權限放在前面以提高效率。
  • 對象級權限:對于需要檢查特定對象的權限(如編輯某個資源),可以在視圖中調用 self.check_object_permissions(request, obj),觸發權限類的 has_object_permission 方法。
  • 錯誤信息:可以通過權限類的 message 屬性自定義錯誤提示。例如:
class IsPremiumUser(BasePermission):message = "You must be a premium user to access this resource."def has_permission(self, request, view):return request.user.is_authenticated and request.user.is_premium
常見使用場景
  • 限制訪問:僅允許認證用戶或特定角色(如管理員、訂閱者)訪問 API。
  • 只讀訪問:允許匿名用戶讀取數據,但限制寫操作。
  • 動態權限:根據請求方法(GET、POST 等)或資源類型動態調整權限。

3. self.check_throttles(request)

作用

self.check_throttles(request) 用于限制請求速率(rate limiting),防止 API 被濫用。它基于 throttle_classes 屬性中定義的限制類,檢查用戶或 IP 的請求頻率是否超出限制。如果超出限制,DRF 會拋出 Throttled 異常,導致返回 429 Too Many Requests 響應。

實現原理

check_throttles 方法會遍歷 self.throttle_classes 中定義的限制類,調用每個限制類的 allow_request 方法:

def check_throttles(self, request):for throttle in self.get_throttles():if not throttle.allow_request(request, self):self.throttled(request, throttle.wait())
  • 限制類:每個限制類繼承自 rest_framework.throttling.BaseThrottle,并實現 allow_request 方法,決定是否允許當前請求。
  • 檢查邏輯allow_request 返回 True 表示請求允許,False 表示請求被限制。如果被限制,throttle.wait() 返回預計的等待時間(秒),并包含在 429 響應中。
  • 緩存支持:DRF 的限制機制通常依賴緩存(如 Redis 或 Django 的內存緩存)來跟蹤請求頻率。
執行時機

check_throttlesinitial 方法中,在 perform_authenticationcheck_permissions 之后調用。這是因為速率限制通常需要基于用戶身份或 IP 地址,而這些信息在認證后更明確。

配置限制類

可以通過 throttle_classes 屬性指定限制。例如:

from rest_framework.views import APIView
from rest_framework.throttling import UserRateThrottleclass MyAPIView(APIView):throttle_classes = [UserRateThrottle]def get(self, request):return Response({"message": "Request allowed"})
內置限制類

DRF 提供了一些常用的限制類:

  • AnonRateThrottle: 限制匿名用戶的請求速率,基于 IP 地址。
  • UserRateThrottle: 限制認證用戶的請求速率,基于用戶 ID。
  • ScopedRateThrottle: 限制特定視圖的請求速率,可以通過 throttle_scope 屬性配置。

限制速率在 settings.py 中通過 REST_FRAMEWORK 配置。例如:

REST_FRAMEWORK = {'DEFAULT_THROTTLE_CLASSES': ['rest_framework.throttling.AnonRateThrottle','rest_framework.throttling.UserRateThrottle',],'DEFAULT_THROTTLE_RATES': {'anon': '100/day',  # 匿名用戶每天 100 次請求'user': '1000/day',  # 認證用戶每天 1000 次請求}
}
自定義限制

可以創建自定義限制類。例如,限制特定用戶組的請求速率:

from rest_framework.throttling import SimpleRateThrottleclass PremiumUserThrottle(SimpleRateThrottle):scope = 'premium'def get_cache_key(self, request, view):if request.user.is_authenticated and request.user.is_premium:return f"throttle_{request.user.id}"return None

settings.py 中配置:

REST_FRAMEWORK = {'DEFAULT_THROTTLE_RATES': {'premium': '5000/day',}
}
注意事項
  • 緩存依賴:速率限制通常需要配置緩存后端(如 Redis),否則可能無法正常工作。
  • 匿名用戶限制:基于 IP 的限制可能不準確,因為多個用戶可能共享同一 IP(如代理服務器)。
  • 動態限制:可以通過 throttle_scope 和自定義限制類實現基于視圖或用戶的動態限制。
  • 錯誤響應:429 響應會包含 Retry-After 頭,指示客戶端需要等待的時間。
常見使用場景
  • 防止濫用:限制匿名用戶對公開 API 的頻繁訪問。
  • 分級服務:為不同用戶組(如免費用戶、付費用戶)設置不同的請求速率。
  • 保護資源:避免服務器因高頻請求過載。

綜合分析與優化建議

執行順序的意義

perform_authenticationcheck_permissionscheck_throttles 的調用順序是有意設計的:

  1. 先認證:確保 request.userrequest.auth 已設置,因為權限和限制可能依賴這些信息。
  2. 再檢查權限:基于認證結果判斷用戶是否有權訪問資源。
  3. 最后限制速率:確保只有合法請求才會計入速率限制,避免浪費配額。
性能優化
  • 認證:選擇輕量級的認證方式(如 JWT 比 Session 更適合無狀態 API),并緩存頻繁查詢的用戶數據。
  • 權限:將復雜的權限檢查邏輯移到對象級(has_object_permission),減少視圖級檢查的開銷。
  • 限制:使用高效的緩存后端(如 Redis),并合理設置限制周期(如小時、天)以平衡性能和安全性。
擴展性
  • 模塊化設計:DRF 的認證、權限和限制機制高度模塊化,允許通過自定義類實現復雜邏輯。
  • 全局配置:在 settings.py 中通過 REST_FRAMEWORK 設置默認的認證、權限和限制類,減少重復代碼。
  • 動態調整:通過 get_authenticatorsget_permissionsget_throttles 方法動態返回認證、權限或限制類,實現基于視圖或請求的靈活配置。
常見問題與解決方案
  • 401 vs. 403
    • 401 Unauthorized:認證失敗(如無效的令牌)。
    • 403 Forbidden:認證成功但權限不足。
    • 解決方案:確保認證和權限類的錯誤信息清晰,方便調試。
  • 速率限制不生效:檢查是否正確配置了緩存后端(如 CACHES 設置)。
  • 匿名用戶問題:明確區分匿名和認證用戶的處理邏輯,避免意外允許敏感操作。
實際案例

假設你正在開發一個博客 API,需求如下:

  • 匿名用戶可以讀取文章(GET)。
  • 認證用戶可以創建文章(POST),但每天限制 10 次請求。
  • 管理員可以編輯所有文章(PUT)。

實現代碼如下:

from rest_framework.views import APIView
from rest_framework.permissions import IsAuthenticated, IsAdminUser
from rest_framework.throttling import UserRateThrottle
from rest_framework.response import Responseclass ArticleAPIView(APIView):authentication_classes = [TokenAuthentication]permission_classes = [IsAuthenticated]throttle_classes = [UserRateThrottle]def get_permissions(self):if self.request.method == 'GET':return [AllowAny()]elif self.request.method == 'PUT':return [IsAdminUser()]return super().get_permissions()def get(self, request):return Response({"message": "List of articles"})def post(self, request):return Response({"message": "Article created"})def put(self, request):return Response({"message": "Article updated"})

settings.py 中:

REST_FRAMEWORK = {'DEFAULT_THROTTLE_RATES': {'user': '10/day',}
}

總結

  • perform_authentication:負責用戶認證,將用戶信息綁定到請求對象,依賴 authentication_classes
  • check_permissions:檢查用戶權限,決定是否允許訪問,依賴 permission_classes
  • check_throttles:限制請求速率,防止濫用,依賴 throttle_classes
  • 設計哲學:DRF 通過模塊化的認證、權限和限制機制,提供靈活且可擴展的 API 開發框架。
  • 優化與實踐:合理配置認證、權限和限制類,結合緩存和動態調整,滿足復雜業務需求。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/89956.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/89956.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/89956.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

神經網絡——卷積層

目錄 卷積層介紹 Conv2d 卷積動畫演示 卷積代碼演示 綜合代碼案例 卷積層介紹 卷積層是卷積神經網絡(CNN)的核心組件,它通過卷積運算提取輸入數據的特征。 基本原理 卷積層通過卷積核(過濾器)在輸入數據&…

神經網絡——線性層

在機器學習中,線性層(Linear Layer) 是一種基礎的神經網絡組件,也稱為全連接層(Fully Connected Layer) 或密集層(Dense Layer)。 其嚴格的數學定義為:對輸入數據執行線…

大模型高效適配:軟提示調優 Prompt Tuning

The Power of Scale for Parameter-Efficient Prompt Tuning ruatishi 軟提示向量 具體是什么 《The Power of Scale for Parameter-Efficient Prompt Tuning》中增加的部分是“軟提示(soft prompts)”,這是一種針對特定下游任務,添加到輸入文本中的可調參數序列。它與傳統…

https正向代理 GoProxy

背景: 在安全隔離的內網環境中,部署于內網的應用如需調用公網第三方接口(如支付、短信),可通過正向代理服務實現訪問。 GoProxy 下載: https://github.com/snail007/goproxy/releases 使用文檔&#xff…

Java IO流體系詳解:字節流、字符流與NIO/BIO對比及文件拷貝實踐

一、字節流與字符流:如何選擇? 1.1 核心區別特性字節流字符流處理單位字節(8位)字符(16位Unicode)適用場景二進制文件(圖片/視頻)文本文件(TXT/CSV)編碼處理需…

QT6 源,七章對話框與多窗體(5) 文件對話框 QFileDialog 篇二:源碼帶注釋

&#xff08;13&#xff09;本源代碼定義于頭文件 qfiledialog . h &#xff1a; #ifndef QFILEDIALOG_H #define QFILEDIALOG_H#include <QtWidgets/qtwidgetsglobal.h> #include <QtCore/qdir.h> #include <QtCore/qstring.h> #include <QtCore/qurl.h…

關于Ajax的學習筆記

Ajax概念&#xff1a;是一門使用了js語言&#xff0c;可以使用于Javaweb&#xff0c;實現前端代碼和后端代碼連結的的一種異步同步&#xff08;不需要等待服務器相應&#xff0c;就能夠發送第二次請求&#xff09;的一種技術&#xff0c;它主要用于網頁內容的局部刷新&#xff…

The Missing Semester of Your CS Education 學習筆記以及一些拓展知識(三)

文章目錄The Missing Semester of Your CS Education 學習筆記以及一些拓展知識Vim編輯器筆記部分程序員常用的編輯器Vim的模式Vim的普通模式Vim的插入模式Vim的可視模式Vim的替換模式Vim的命令行模式Vim的高級功能文本對象宏寄存器緩沖區標記代碼折疊Vim的常用配置Vim的常用插…

PyTorch常用的簡單數學運算

一、基礎算術運算1. 逐元素運算a torch.tensor([1, 2, 3]) b torch.tensor([4, 5, 6])# 加減乘除 a b # [5, 7, 9] a - b # [-3, -3, -3] a * b # [4, 10, 18] a / b # [0.25, 0.4, 0.5]# 冪運算、平方根 a ** 2 # [1, 4, 9] torch.sqrt(a) # [1.0, 1.414, 1.732]2. 標…

C++ Lambda 表達式詳解:從基礎到實戰

Lambda 表達式是 C11 引入的重要特性&#xff0c;它允許我們在代碼中定義匿名函數&#xff0c;極大地簡化了代碼編寫&#xff0c;尤其是在使用 STL 算法和多線程編程時。本文將詳細介紹 Lambda 表達式的語法、特性及實際應用場景。什么是 Lambda 表達式&#xff1f;Lambda 表達…

Spring Boot注解詳解

文章目錄前言1. 核心啟動注解SpringBootApplicationEnableAutoConfigurationSpringBootConfiguration2. 組件注解Component及其衍生注解ComponentServiceRepositoryControllerRestController3. 依賴注入注解AutowiredQualifierPrimary4. Web相關注解請求映射注解RequestMapping…

Web開發:ABP框架12——中間件Middleware的創建和使用

一、簡介中間件可以用于鑒權、日志&#xff0c;攔截器可以用于指定方法或url的業務邏輯處理&#xff0c;兩者分工不同&#xff0c;實現效果相似&#xff0c;先執行中間件&#xff0c;后執行攔截器&#xff0c;再到WebAPI接口。二、示例一個Token驗證中間件三、代碼1.Startup.cs…

京東商品評論如何獲取?API接口實戰指南

一、API接入準備1. 注冊開發者賬號訪問京東開放平臺&#xff1a;前往京東開放平臺注冊賬號&#xff0c;完成企業或個人實名認證。創建應用&#xff1a;在控制臺創建應用&#xff0c;獲取App Key和App Secret&#xff08;用于簽名認證&#xff09;。2. 申請API權限搜索接口&…

leetcode-sql-627變更性別

題目&#xff1a; Salary 表&#xff1a; --------------------- | Column Name | Type | --------------------- | id | int | | name | varchar | | sex | ENUM | | salary | int | --------------------- id 是這個表的主鍵…

【學習路線】C#企業級開發之路:從基礎語法到云原生應用

一、C#基礎入門&#xff08;1-2個月&#xff09; &#xff08;一&#xff09;開發環境搭建Visual Studio安裝配置 Visual Studio Community&#xff1a;免費版本&#xff0c;功能完整Visual Studio Code&#xff1a;輕量級&#xff0c;跨平臺支持JetBrains Rider&#xff1a;專…

Planning Agent:基于大模型的動態規劃與ReAct機制,實現復雜問題自適應執行求解

引言 在當今數據驅動的商業環境中&#xff0c;企業面臨著日益復雜的決策問題。傳統的數據分析工具往往難以應對多步驟、多依賴的復雜問題求解。例如&#xff0c;當企業需要分析"北美市場 Q1-Q2 主要產品的銷售增長趨勢并識別關鍵驅動因素"時&#xff0c;傳統工具可能…

人該怎樣活著呢?55

人該怎樣活著呢&#xff1f; A思考現實問題并記錄自己的靈感 。【生活的指南針】 &#xff08;20250212&#xff09; a1如何思考&#xff1f; 當有人問他用什么方法得到那么多發現時&#xff0c;牛頓說&#xff1a;“我只不過對于一件事情&#xff0c;總是花很長時間很熱…

rtthread - V5.1.0版本 HOOK 鉤子函數總結

rtthread - V5.1.0版本 鉤子函數 相對于V4.0.3版本做了很大的修改和優化&#xff1a;舊版本 V4.0.3&#xff1a;rt_thread_inited_sethook(thread_inited_hook);rt_thread_deleted_sethook(thread_deleted_hook);rt_scheduler_sethook(scheduler_hook);新版本 V5.1.0&#xff1…

Python特性:裝飾器解決數據庫長時間斷連問題

前言 在基于 Python 的 Web 應用開發里&#xff0c;數據庫連接是極為關鍵的一環。不過&#xff0c;像網絡波動、數據庫服務器維護這類因素&#xff0c;都可能造成數據庫長時間斷連&#xff0c;進而影響應用的正常運作。本文將詳細介紹怎樣運用 retry_on_failure 裝飾器來解決數…

療愈之手的智慧覺醒:Deepoc具身智能如何重塑按摩機器人的觸覺神經

療愈之手的智慧覺醒&#xff1a;Deepoc具身智能如何重塑按摩機器人的觸覺神經康復中心的理療室內&#xff0c;一位運動員正俯臥在治療床上。機械臂的硅膠觸頭沿腰背肌群緩緩移動&#xff0c;當傳感器捕捉到豎脊肌的異常僵直時&#xff0c;觸頭自動切換高頻震顫模式&#xff1b;…