在 Rest Framework 中提供了兩個(gè) router , 可以幫助我們快速的實(shí)現(xiàn)路由的自動(dòng)生成。
必須是繼承 ModelViewSet 的視圖類才能自動(dòng)生成路由
使用方法:
urls.py
# 第一步:導(dǎo)入routers模塊 from rest_framework import routers # 第二步:實(shí)例化得到對(duì)象 router = routers.SimpleRouter() # 第三步:注冊(cè)( register('前綴', viewset視圖集, 路由的別名) ) router.register('books', views.BooksViewset) # 第四步:生成路由加入到原路由中 # 方式一: urlpatterns = [ ... ] urlpatterns += router.urls # 方式二: urlpatterns = [ ... url(r'^', include(router.urls)) ] # 形成路由如下 URLPattern '^books/$' [name='books-list']> URLPattern '^books/(?Ppk>[^/.]+)/$' [name='books-detail']>
DefaultRouter與SimpleRouter的區(qū)別是,DefaultRouter會(huì)多附帶一個(gè)默認(rèn)的API根視圖,返回一個(gè)包含所有列表視圖的超鏈接響應(yīng)數(shù)據(jù)。
# 前兩條和SimpleRouter一樣 URLPattern '^books/$' [name='books-list']> URLPattern '^books/(?Ppk>[^/.]+)/$' [name='books-detail']> # 效果也和前兩條類似, # 如:http://127.0.0.1:8000/books.json URLPattern '^books\.(?Pformat>[a-z0-9]+)/?$' [name='books-list']> # http://127.0.0.1:8000/books/1.json URLPattern '^books/(?Ppk>[^/.]+)\.(?Pformat>[a-z0-9]+)/?$' [name='books-detail']> # 多了個(gè)根路由http://127.0.0.1:8000/ URLPattern '^$' [name='api-root']>, URLPattern '^\.(?Pformat>[a-z0-9]+)/?$' [name='api-root']>
action是為了給繼承自 ModelViewSet 的視圖類中自定義的函數(shù)也添加路由
例如下面這樣:
from rest_framework.viewsets import ModelViewSet from rest_framework.response import Response from app01.ser import BooksSerializers from app01.models import Books class BooksViewSet(ModelViewSet): queryset = Books.objects.all() serializer_class = BooksSerializers # 這種方法不會(huì)自動(dòng)生成,需要用action配置 def get_num(self, request, pk): book = self.get_queryset()[:int(pk)] ser = self.get_serializer(book, many=True) return Response(ser.data)
使用示例:
action是一個(gè)裝飾器,放在被裝飾的函數(shù)上方,
method:請(qǐng)求方式
detail:是否帶pk ——>True 表示路徑格式是xxx/pk>/action方法名/
——False 表示路徑格式是xxx/action方法名/
from rest_framework.viewsets import ModelViewSet from rest_framework.response import Response from rest_framework.decorators import action from app01.ser import BooksSerializers from app01.models import Books class BooksViewSet(ModelViewSet): queryset = Books.objects.all() serializer_class = BooksSerializers @action(methods=['GET', 'POST'], detail=True) def get_num(self, request, pk): book = self.get_queryset()[:int(pk)] # 獲取前幾條數(shù)據(jù) ser = self.get_serializer(book, many=True) return Response(ser.data) # 生成路由如下 http://127.0.0.1:8000/books/2/get_num/ URLPattern '^books/(?Ppk>[^/.]+)/get_num/$' [name='books-get-num']>
認(rèn)證的寫法
authentication_classes = [認(rèn)證類1]
中# 全局使用,在setting.py中配置 REST_FRAMEWORK={ "DEFAULT_AUTHENTICATION_CLASSES":["app01.app_auth.MyAuthentication",] } # 局部使用,在視圖類上寫 authentication_classes=[MyAuthentication] # 局部禁用 authentication_classes=[]
1、APIView重寫as_view方法使之沒有csrf認(rèn)證——>但還是正常執(zhí)行 dispatch 方法,但是 dispatch方法被 APIView重寫了——>dispatch 中執(zhí)行了 self.initial 認(rèn)證方法——>有認(rèn)證,權(quán)限,頻率
2、現(xiàn)在只是看認(rèn)證源碼self.perform_authentication(request)
3、但是self.perform_authentication(request)
就一句話:request.user
,那么就需要去 drf 的 Request 對(duì)象中找 user 屬性(方法)
@property def user(self): # 先去判斷當(dāng)前對(duì)象中有沒有'_user'這個(gè)屬性,一開始肯定是沒有的,因?yàn)橛脩羰菦]有登錄的 if not hasattr(self, '_user'): with wrap_attributeerrors(): # 沒有用戶,認(rèn)證出用戶 self._authenticate() # 有用戶,直接返回用戶 return self._user
4、Request 類中的 user 方法,剛開始來,沒有_user
,走 self._authenticate()
5、核心,就是Request類中的 _authenticate(self)
def _authenticate(self): # 遍歷拿到一個(gè)認(rèn)證器,進(jìn)行認(rèn)證 # self.authenticators 配置的一堆認(rèn)證類產(chǎn)生的認(rèn)證類對(duì)象組成的 list # self.authenticators 就是在視圖類中配置的:authentication_classes = [認(rèn)證類1,認(rèn)證類2] 的一個(gè)個(gè)認(rèn)證類的對(duì)象: ————>self.authenticators ==》 [認(rèn)證類1對(duì)象,認(rèn)證類2對(duì)象] for authenticator in self.authenticators: try: # 認(rèn)證器調(diào)用認(rèn)證方法authenticate(認(rèn)證類對(duì)象self,request對(duì)象) """ def authenticate(self, request): return (self.force_user, self.force_token) """ # 返回值:登錄的用戶與認(rèn)證的信息組成的 tuple # 并且該方法被try包裹,就代表該方法會(huì)拋異常,拋異常就代表認(rèn)證失敗 user_auth_tuple = authenticator.authenticate(self) # self是request對(duì)象 except exceptions.APIException: self._not_authenticated() raise # 返回值的處理 if user_auth_tuple is not None: self._authenticator = authenticator # 如果有返回值,就將 "登錄用戶" 與 "登錄認(rèn)證" 分別保存到 request.user / request.auth self.user, self.auth = user_auth_tuple return # 如果返回值user_auth_tuple為空,代表認(rèn)證通過,但是沒有 "登錄用戶" 與 "登錄認(rèn)證信息",代表游客 self._not_authenticated()
1、寫一個(gè)認(rèn)證類,繼承 BaseAuthentication,重寫 authenticate
# app01_auth.py from rest_framework.authentication import BaseAuthentication from rest_framework.exceptions import AuthenticationFailed from app01.models import UserToken class TokenAuthentication(BaseAuthentication): def authenticate(self, request): # 認(rèn)證邏輯,如果認(rèn)證通過,返回兩個(gè)值 # 如果認(rèn)證失敗,拋出AuthenticationFailed異常 token = request.data.get('token') if token: user_token = UserToken.objects.filter(token=token).first() # 認(rèn)證通過 if user_token: return UserToken.user, token else: raise AuthenticationFailed('認(rèn)證失敗') else: raise AuthenticationFailed('請(qǐng)求地址中需要帶token')
2、將認(rèn)證類添加到需要認(rèn)證視圖類的authentication_classes = [認(rèn)證類1]
中
# views.py from rest_framework.viewsets import ModelViewSet from rest_framework.views import APIView from rest_framework.response import Response from app01.models import Books, UserInfo, UserToken from app01.ser import BooksSerializer from app01.app01_auth import TokenAuthentication import uuid # 查看Books需要經(jīng)過認(rèn)證才能查看 class BooksView(ModelViewSet): authentication_classes = [TokenAuthentication] queryset = Books.objects.all() serializer_class = BooksSerializer # 登錄視圖,登錄后獲得token,后續(xù)用token認(rèn)證 class LoginView(APIView): def post(self, request): response_msg = {'status': 200, 'msg': ''} username = request.data.get('username') password = request.data.get('password') user_obj = UserInfo.objects.filter(username=username, password=password).first() if user_obj: # 登錄成功生成一個(gè)隨機(jī)字符串 token = uuid.uuid4() # 存到UserToken表中,update_or_create有就更新,沒有就新增 UserToken.objects.update_or_create(defaults={'token': token}, user=user_obj) response_msg['msg'] = '登錄成功' response_msg['token'] = token else: response_msg['msg'] = '賬戶或密碼錯(cuò)誤' response_msg['status'] = 204 return Response(response_msg)
到此這篇關(guān)于drf-router和authenticate認(rèn)證源碼分析的文章就介紹到這了,更多相關(guān)drf-router和authenticate內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
標(biāo)簽:上饒 珠海 佳木斯 宜昌 西寧 湖北 盤錦 潮州
巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《drf-router和authenticate認(rèn)證源碼分析》,本文關(guān)鍵詞 drf-router,和,authenticate,認(rèn)證,;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問題,煩請(qǐng)?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無關(guān)。