一,認(rèn)證組件
(1)?? 設(shè)置認(rèn)證,只有通過的用戶才能訪問指定的url地址
(2)?? 寫認(rèn)證的類父元素是APIview,rest_framework源碼dispatch里面調(diào)用了封裝之后的request,調(diào)用initial方法里面調(diào)用了perform_authentication方法,返回的是user/auth倆值,我們寫認(rèn)證則要重新定義perform_authentication,根據(jù)token來匹配數(shù)據(jù)庫做判斷返回相對應(yīng)的返回.
(3)寫好之后需要在setting文件中配置
這里鍵是根據(jù)APIview下方設(shè)置的中間件來定義的
???????????? api_settings.DEFAULT_AUTHENTICATION_CLASSES
???????????? REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES'['unitls.authentication.MyOrderAuthentication'],
???????????? }
(這里設(shè)置的是全局認(rèn)證),如果是局部認(rèn)證只需要在view中需要認(rèn)證的地方寫入
??????????? authentication_classes = [這里是自己定義的認(rèn)證類]
**注意的是如果開啟全局認(rèn)證用戶登錄前需要關(guān)閉認(rèn)證則要寫入**
???????????? authentication_classes = []
注冊成功之后要存數(shù)據(jù)庫,用來后面登錄做匹配
??????????????? username = request._request.POST.get('username')
??????????????? password = request._request.POST.get('password')
? 這里為們要用md5加碼生成token然后保存
????????????? token = md5(username,password)
????????????? # 將token保存
??????????????? UserToken.objects.update_or_create(
??????????????? user=obj,defaults={'token':token},
????????????????? )
保存后面登錄根據(jù) 生成的token來做匹配判斷
二,權(quán)限
(1)?? 給用戶設(shè)置權(quán)限,只有登錄用戶并且是指定用戶才能訪問
(2)?? 和認(rèn)證方法大致相同在initial方法下調(diào)用
self.check_permissions(request),進入到check_permissions函數(shù)中發(fā)現(xiàn)里面是做一個對象循環(huán)判斷
????????????? if not permission.has_permission(request, self):
#在自定義的Permission中has_permission方法是必須要有的
#判斷當(dāng)前has_permission返回的是True,F(xiàn)alse禁灼,還是拋出異常
#如果是True則表示權(quán)限通過,False執(zhí)行下面代碼
#為False的話則拋出異常忱叭,當(dāng)然這個異常返回的提示信息是英文的,如果我們想讓他顯示我們自定義的提示信息
#我們重寫permission_denied方法即可
???????????? self.permission_denied(
#從自定義的Permission類中獲取message(權(quán)限錯誤提示信息),一般自定義的話都建議寫上,如果沒有則為默認(rèn)的(英文提示)
??????????????? self.permission_denied(
?????????????? request,message=getattr(permission,'message',None)
??????????????? )
只需要更改message值就行比如
message ='你不是超級用戶隔崎,沒有權(quán)限訪問'
(---------)例如我在下面寫了一個判斷3表示的是svip用戶
??????????? def has_permission(self, request, view):
"""
????????????????????? Return `True` if permission is granted, `False` otherwise.
? ? 返回True表示有權(quán)限訪問,返回False表示沒有權(quán)限訪問"""
? ???????????????????? if request.user.user_type !=3:
?????????????????????????????? return False
? ? ? ? ? ? ? ? ? ? ? ? return True
******全局配置
REST_FRAMEWORK = {
"DEFAULT_PERMISSION_CLASSES":[自己寫權(quán)限類的路徑]
}
三,節(jié)流
有些時候為了對用戶的訪問頻率進行限制和防止爬蟲韵丑,需要在規(guī)定的時間中對用戶訪問的次數(shù)進行限制
(1),源碼入口dispatch--------->>執(zhí)行認(rèn)證? self.initial ------->>頻率控制self.check_throttles(request)里面做循環(huán)判斷,
for? throttlein self.get_throttles():
? ? ? if? not throttle.allow_request(request, self):
? ? ? ? ? ? ? ? self.throttled(request, throttle.wait())
如果沒有通過會返回 false 執(zhí)行 self.throttled(request, throttle.wait()),拋出異常---------返回True表示可以繼續(xù)訪問
def get_throttles(self):
?????????? # 返回訪問頻率控制的
????????? return[throttle()? for??? throttle?? in??? self.throttle_classes]--------------->>
所以說我們需要進行節(jié)流限制接口設(shè)置類屬性
throttle_class = [ 節(jié)流限制的類 ]
我們需要重寫allow_request(request, self) 和 wait 方法
**全局設(shè)置
REST_FRAMEWORK = {
"DEFAULT_THROTTLE_CLASSES":{
'unlogin':'10/m',
?'logined':'3/m'
}
這里的unlogin和logined是我們在節(jié)流類下面寫入----->>類:scope ='logined'
四,版本
1,類:在新版本上線,老版本不能直接刪除情況下爵卒,用到版本控制
2,? 進口dispatch ---->>initial下面有版本控制源碼
version, scheme =self.determine_version(request, *args, **kwargs)
request.version, request.versioning_scheme = version, scheme
3,這里調(diào)用方法self.determine_version,進入看到
def determine_version(self, request, *args, **kwargs):
?????? if self.versioning_classis None:
???????????????? return (None,None)
????? scheme =self.versioning_class()
?????? return (scheme.determine_version(request, *args, **kwargs), scheme)
(1)versioning_classis是在setting中定義的版本控制類
(2)versioning_class()進行定義的版本控制類實例化賦值給了scheme
(3) 最后return中 執(zhí)行版本控制類中的determine_version方法,返回version,
4,scheme.determine_version的執(zhí)行取決與我們所引用的版本控制類是哪一個,我們一般都用URLPathVersioning和QueryParameterVersioning
導(dǎo)入后點進入URLPathVersioning,里面發(fā)現(xiàn)調(diào)用is_allowed_version方法,這里做判斷是否能訪問當(dāng)前版本
return((version? is? not? None? and? version == self.default_version) or
(version in self.allowed_versions))
到這我們就獲取到訪問版本的類,回到開始-------------------------------
version, scheme = self.determine_version(request, *args, **kwargs)
request.version, request.versioning_scheme = version, scheme
我們將version 和scheme封裝在request中如果我們訪問的版本符合要求我們可以通過調(diào)用
request.version, request.versioning_scheme 來獲得版本號和控制版本的類
5,自己定義版本類模塊,定義函數(shù)determine_version做版本控制配置路由要改變,,,,類:
url(r"^(?P<version>[v1|v2]+)/userinfo/", UserInfoView.as_view(),name='vvvv')
6,全局設(shè)置
'DEFAULT_THROTTLE_CLASSES':['unitls.throll.VisitThrottle'],
#設(shè)置版本的參數(shù)
'VERSION_PARAM':'version',
'DEFAULT_VERSION':'v1',
'ALLOWED_VERSIONS':['v1','v2'],
五,解析器
1,解析器是對我們請求體中的數(shù)據(jù)進行反序列化撵彻、封裝 把我們的所有的請求數(shù)據(jù)都封裝在request.data中 在request.data中獲取數(shù)據(jù)
2,使用
(1)獲取用戶請求
(1)獲取用戶請求體
(3)根據(jù)用戶請求頭信息和parase_classes=[...],中的請求頭進行比較钓株,匹配上請求頭就使用該解析器處理
(4)解析器從請求體中拿數(shù)據(jù)進行處理,處理完成之后將結(jié)果返回給request.data
-------------------------------------------------------------------
要導(dǎo)入模塊
from rest_framework.parsers?? import FormParser,? JSONParser
添加局部認(rèn)證
parser_classes = [FormParser, JSONParser]
(1)然后獲取數(shù)據(jù),正常的post請求
瀏覽器中media_type形式為
media_type ='application/x-www-form-urlencoded'
(2)如果這里發(fā)送的是json數(shù)據(jù)則返回null空取不到數(shù)據(jù)
我們就可以在request的data中獲取數(shù)據(jù)data = request.data