Django框架之drf:7、認證元件,許可權元件,頻率元件,過濾的多種用法,排序,分頁,

2023-02-08 06:00:56

Django框架之drf

一、認證元件

簡介

​ 登入認證的限制

​ 認證元件是drf框架給我們提供的認證介面,它能夠在請求進入檢視函數/類前進驗證(例如:認證使用者是否登入),對不符合認證的請求進行攔截並返回校驗失敗的資訊

1、認證元件使用步驟

模組地址:

from rest_framework.authentication import BaseAuthentication

用法簡介:

# 1、建立一個專門用於認證的py檔案,寫一個類繼承BaseAuthentication
# 2、重寫authenticate方法,在方法內驗證token
# 3、如果認證成功,返回兩個值【返回None或兩個值(當前登入的物件和token)】
# 4、認證不通過,拋異常AuthenticationFailed(異常資訊)
# 5、區域性使用和全域性使用
	-區域性使用:# 在需要使用認證的檢視類下管理介面
        class BookDetailView(ViewSetMixin, RetrieveAPIView):
           authentication_classes = [LoginAuth] # 列表,可以新增多個
    
	-全域性使用:# 在django的setting.py檔案種新增設定
       		REST_FRAMEWORK = {
    	'DEFAULT_AUTHENTICATION_CLASSES':['app01.authenticate.LoginAuth']
				}
 
	-區域性禁用:# 全域性開啟,區域性禁用
    	class BookDetailView(ViewSetMixin, RetrieveAPIView):
            authentication_classes = [] 

2、程式碼用法

認證類程式碼:(authentica.py)

class LoginAuth(BaseAuthentication):
    # 在這裡實現認證,如果是登入的,繼續往後走返回兩個值,如果不是拋異常
    def authenticate(self, request):
        # 請求中是否攜帶token,判斷是否登入,放在位址列中
        token = request.query_params.get('token', None)
        # 判斷前端是否傳入token
        if token:  
            # 去表中查詢token
            user_token = UserToken.objects.filter(token=token).first()
            # 判斷是否查到token
            if user_token:
                # 找到了返回兩個值:登入的物件和token
                return user_token.user, token
            else:
                # 沒有登入拋異常
                raise AuthenticationFailed('token認證失敗')
        else:
            raise AuthenticationFailed('token沒傳')	

檢視類程式碼

# 查詢所有
class BookView(ViewSetMixin, ListAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    # 控制認證的介面(列表,可以在認證的py檔案下編寫多個認證)
    authentication_classes = [LoginAuth]  # 區域性認證

路由程式碼

from django.urls import path, include
from app01 import views

# 第一步:匯入模組
from rest_framework.routers import SimpleRouter

# 第二步:範例化物件
router = SimpleRouter()

# 第三步:註冊路由
router.register('books', views.BookView, 'books')

urlpatterns = [
    path('', include(router.urls))
]

二、許可權元件

簡介:

​ 在我們使用的一些app或者網頁中(愛奇藝,騰訊視訊),都會有一些會員介面(需要購買會員才能夠使用或者觀看),許可權元件就是對使用者的這一許可權進行驗證,在請求進入檢視類/函數程式碼前進行校驗,校驗失敗後直接將請求攔截,並返回校驗失敗的資訊

1、許可權元件的使用步驟

模組地址:

from rest_framework.permissions import BasePermission

用法簡介:

# 1、建立一個專門用於編寫許可權元件的py檔案,寫一個許可權類,繼承BasePermission
# 2、重寫has_permission方法(在該方法在中實現許可權認證,在這方法中,request.user就是當前登入使用者)
# 3、如果有許可權,返回True
# 4、沒有許可權,返回False(客製化返回的中文: self.message='中文')
# 5、區域性使用和全域性使用
	-區域性使用: # 在某個檢視類中設定介面(不會影響別的檢視類)
        class BookDetailView(ViewSetMixin, RetrieveAPIView):
            permission_classes = [CommonPermission]

	-全域性使用:  # django的settings.py中設定,影響全域性
    	REST_FRAMEWORK = {
            'DEFAULT_PERMISSION_CLASSES': [
                'app01.permissions.CommonPermission',
            ],
        }
  
	-區域性禁用:# 全域性設定區域性禁用
        class BookDetailView(ViewSetMixin, RetrieveAPIView):
            permission_classes = [] 

2、程式碼用法

許可權類程式碼(perssion.py)

# 寫許可權類,寫一個類,繼承基礎類別BasePermission,重寫has_permission方法,在方法中實現許可權認證,如果有許可權return True ,如果沒有許可權,返回False
from rest_framework.permissions import BasePermission


class CommonPermission(BasePermission):
    def has_permission(self, request, view):
        # 實現許可權的控制  ---》知道當前登入使用者是誰?當前登入使用者是  request.user
        if request.user.user_type == 1:
            return True
        else:
            # 沒有許可權,向物件中放一個屬性 message
            # 如果表模型中,使用了choice,就可以通過  get_欄位名_display()  拿到choice對應的中文
            self.message = '您是【%s】,您沒有許可權' % request.user.get_user_type_display()
            return False

檢視類程式碼:

class BookView(ModelViewSet):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    # 區域性認證
    authentication_classes = [LoginAuth]
    # 許可權認證(將編寫的頻率類匯入過來)
    permission_classes = [CommentPermission]

三、頻率

簡介:

​ 頻率是指,控制某個介面存取頻率(次數)

1、頻率元件的使用步驟

模組地址:

from rest_framework.throttling import BaseThrottle, SimpleRateThrottle
# BaseThrottle:需要手動編寫的程式碼較多
# SimpleRateThrottle: 需要手動編寫的程式碼較少(用這個)

用法簡介

# 1、建立一個專門用來編寫頻率元件的py檔案,寫一個頻率類,繼承SimpleRateThrottle
# 2、重寫get_cache_key方法,返回什麼,就以什麼做限制----》ip(使用者id做限制)
# 3、設定一個類屬性scope = 'book_5_m'
# 4、在django的組態檔中編寫頻率次數
	REST_FRAMEWORK = {
          'DEFAULT_THROTTLE_RATES': {
            'book_5_m': '5/m',  # 一分鐘五次 
        },
    	}
# 5、區域性使用和全域性使用
	-區域性使用: # 隻影響當前的檢視類
    class BookView(ModelViewSet):
        throttle_classes = [CommentThrottle]
     
    -全域性設定:影響全域性
    	REST_FRAMEWORK = {
             'DEFAULT_THROTTLE_CLASSES': ['app01.throttling.CommonThrottle'],

        }
     
    -區域性禁用:
      class BookView(ModelViewSet):
         throttle_classes = [CommentThrottle]

2、程式碼用法

頻率類程式碼(throttle.py)

from rest_framework.throttling import BaseThrottle, SimpleRateThrottle


class CommentThrottle(SimpleRateThrottle):
    # 建立一個用於控制頻率的變數名(需要傳入組態檔)
    scope = 'book_5_m'

    def get_cache_key(self, request, view):
        # 返回什麼就以什麼做限制(request.META.get('REMOTE_ADDR')以IP做限制)
        return request.META.get('REMOTE_ADDR')

檢視類程式碼

class BookView(ModelViewSet):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    # 頻率元件
    throttle_classes = [CommentThrottle]

django組態檔

REST_FRAMEWORK = {
    # 控制存取頻率
    'DEFAULT_THROTTLE_RATES': {
        'book_5_m': '5/m',  # 一分鐘五次
    },
}

四、過濾的多種用法

簡介:

​ 過濾是指在使用查詢的時候,我們可以通過條件來過濾掉不需要的內容(例如:使用淘寶購物時,購買某種物品,過濾掉價格低於100元的商品)

# restful規範中,要求了,請求地址中帶過濾條件
	-5個介面中,只有一個介面需要有過濾和排序,查詢所有介面

1、繼承APIView自己寫

class BookView(APIView):
    def get(self,request):
        # 獲取get請求攜帶的引數
        name=request.query_params.get('name')
        # 通過filter進行過濾
        books = Book.objects.filter(name=name)

2、使用drf的內建過濾(繼承GenericAPIview)

模組地址:

-該方法為模糊查詢

from rest_framework.filters import SearchFilter

程式碼用法:

class BookView(ModelViewSet):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    # 範例化過濾物件
    filter_backends = [SearchFilter]
    # 指定過濾的欄位(模糊查詢)
    search_fields = ['name', 'price']

搜尋方式:

# name或price中只要有關鍵字就會搜出來 (只能用search=xxx的方式)
	http://127.0.0.1:8000/api/v1/books/?search=西遊記

3、使用第三方外掛過濾(精準過濾)

第三方外掛:

# 外掛名稱:
	django-filter
    
# 安裝外掛:
	pip3.8 install django-filter

模組地址:

from django_filters.rest_framework import DjangoFilterBackend

程式碼用法:

from rest_framework.viewsets import ModelViewSet
from .models import Book
from .serializer import BookSerializer
from django_filters.rest_framework import DjangoFilterBackend


class BookView(ModelViewSet):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

    # 第三方過濾外掛
    filter_backends = [DjangoFilterBackend]
    # 查詢的欄位
    filterset_fields = ['pk','name', 'price']

搜尋方式:

http://127.0.0.1:8000/api/books/?price=99
http://127.0.0.1:8000/api/books/?price=99&name=吶喊

4、使用過濾元件

4、1.客製化過濾元件的使用方式與步驟

模組地址:

from rest_framework.filters import BaseFilterBackend

用法簡介:

# 1、建立一個專門用於過濾的py檔案,寫一個類繼承BaseFilterBackend
# 2、重寫filter_queryset方法,在方法內部進行過濾
# 3、直接返回過濾後的物件
# 4、如果沒有過濾直接返回所有資料
# 5、區域性使用
	 -區域性使用:
    class BookView(ViewSetMixin, ListAPIView):
        queryset = Book.objects.all()
        serializer_class = BookSerializer
        # 在類表內填寫過濾的類
        filter_backends = [CommonFilter]  # 可以客製化多個,從左往右,依次執行

4、2.程式碼用法

過濾類程式碼(filters.py)

from rest_framework.filters import BaseFilterBackend


class CommonFilter(BaseFilterBackend):
    # 重寫的類,編寫過濾吧的內容
    def filter_queryset(self, request, queryset, view):
        # 獲取過濾的條件
        filter_comment = request.query_params.get('price_gt', None)
        # 判斷前端是否傳入過濾條件
        if filter_comment:
            # 根據條件進行賽選內容
            books_queryset_filter = queryset.filter(price__gt=100)
            # 返回過濾後的資料
            return books_queryset_filter
        return queryset

檢視類程式碼

class BookView(ModelViewSet):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

    # 第三方過濾外掛
    filter_backends = [CommonFilter]

五、排序

1、用法簡介

用法簡介:

排序需要和自定義過濾繼承同一個父類別,需要將排序的物件填入在過濾的列表內,並且放在其他引數的前方

模組地址:

from rest_framework.filters import OrderingFilter

2、程式碼用法

檢視類程式碼

from rest_framework.viewsets import ModelViewSet
from .models import Book
from .serializer import BookSerializer
from django_filters.rest_framework import DjangoFilterBackend
from .filters import CommonFilter
from rest_framework.filters import OrderingFilter


class BookView(ModelViewSet):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

    # 第三方過濾外掛(OrderingFilter放在其他過濾引數前)
    filter_backends = [OrderingFilter, DjangoFilterBackend, CommonFilter]
    # 查詢的欄位
    filterset_fields = ['id', 'name', 'price']
    # 指定排序的欄位(-是降序,預設升序)
    ordering_fields = ['price']

搜尋用法

# 預設升序
    http://127.0.0.1:8000/api/books/?price_gt=60&ordering=price
    
# 降序
	http://127.0.0.1:8000/api/books/?price_gt=60&ordering=-price

六、分頁

1、用法簡介

  • 只有查詢所有介面才能到用到分頁
  • drf內建了三個分頁器,分別應對三種分頁方式
  • 內建的分頁類不能直接使用,需要繼承,客製化一些引數後才能使用

2、三種分頁器的用法

模組地址:

​ 三種分頁器在同一個父類別中

from rest_framework.pagination import PageNumberPagination, CursorPagination, LimitOffsetPagination

檢視類程式碼:

class BookView(ModelViewSet):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    # 指定分頁器
    pagination_class = ‘指定使用的分分頁器’(需要匯入分頁器類)

2、1.自定義分頁器

from rest_framework.pagination import PageNumberPagination, CursorPagination, LimitOffsetPagination


# 第一種:通常用於web端(常規分頁器)
class CommonPageNumberPagination(PageNumberPagination):
    # 每頁顯示2條
    page_size = 2
    # page=10  查詢第10頁的資料,每頁顯示2條
    page_query_param = 'page'
    # page=10&size=5    查詢第10頁,每頁顯示5條
    page_size_query_param = 'size'
    # 每頁最大顯示10條
    max_page_size = 5


# 第二種:可以控制每頁顯示的數量(偏移分頁,用的較少)
class CommonLimitOffsetPagination(CursorPagination):
    # 每頁顯示2條
    default_limit = 3
    # limit=3   取3條
    limit_query_param = 'limit'
    # offset=1  從第一個位置開始,取limit條
    offset_query_param = 'offset'
    # 最大顯示數
    max_limit = 5


# 第三種:遊標分頁器(app常用,拉到哪裡顯示多少資料)
class CommonCursorPagination(CursorPagination):
    # 查詢引數(可以隨便寫,需要在前端路由對上)
    cursor_query_param = 'p'
    # 每頁多少條
    page_size = 2
    # 排序的欄位
    ordering = 'id'

前端對應搜尋方式:

#基本分頁方式(基本是這種,網頁端):
	http://127.0.0.1:8000/api/v1/books/?page=2&size=3
    

# 偏移分頁 :從第一條開始,取4條
	http://127.0.0.1:8000/api/v1/books/?limit=4&offset=1

# 遊標分頁:
	http://127.0.0.1:8000/api/books/?p=cD0x