三大認證組件

三大認證組件

認證Authentication

能夠在配置文件中配置全局默認的認證方案前端

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.SessionAuthentication',  # session認證
        'rest_framework.authentication.BasicAuthentication',   # 基本認證
    )
}

也能夠在每一個視圖中經過設置authentication_classess屬性來設置python

from rest_framework.authentication import SessionAuthentication, BasicAuthentication
from rest_framework.views import APIView

class ExampleView(APIView):
    # 類屬性
    authentication_classes = [SessionAuthentication, BasicAuthentication]
    ...

認證失敗會有兩種可能的返回值:數據庫

  • 401 Unauthorized 未認證
  • 403 Permission Denied 權限被禁止

權限Permissions

權限控制能夠限制用戶對於視圖的訪問和對於具體數據對象的訪問。django

  • 在執行視圖的dispatch()方法前,會先進行視圖訪問權限的判斷
  • 在經過get_object()獲取具體對象時,會進行模型對象訪問權限的判斷

使用

能夠在配置文件中全局設置默認的權限管理類,如後端

REST_FRAMEWORK = {
    ....
    
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAuthenticated',
    )
}

若是未指明,則採用以下默認配置api

'DEFAULT_PERMISSION_CLASSES': (
   'rest_framework.permissions.AllowAny',
)

也能夠在具體的視圖中經過permission_classes屬性來設置,如瀏覽器

from rest_framework.permissions import IsAuthenticated
from rest_framework.views import APIView

class ExampleView(APIView):
    permission_classes = (IsAuthenticated,)
    ...
    pass

提供的權限

  • AllowAny 容許全部用戶
  • IsAuthenticated 僅經過認證的用戶
  • IsAdminUser 僅管理員用戶
  • IsAuthenticatedOrReadOnly 已經登錄認證的用戶能夠對數據進行增刪改操做,沒有登錄認證的只能查看數據。

舉例

from rest_framework.authentication import SessionAuthentication
from rest_framework.permissions import IsAuthenticated
from rest_framework.generics import RetrieveAPIView

class StudentAPIView(RetrieveAPIView):
    queryset = Student.objects.all()
    serializer_class = StudentSerializer
    authentication_classes = [SessionAuthentication]
    permission_classes = [IsAuthenticated]

自定義權限

如需自定義權限,需繼承rest_framework.permissions.BasePermission父類,並實現如下兩個任何一個方法或所有服務器

  • .has_permission(self, request, view)session

    是否能夠訪問視圖, view表示當前視圖對象app

  • .has_object_permission(self, request, view, obj)

    是否能夠訪問數據對象, view表示當前視圖, obj爲數據對象

例如:

在當前子應用下,建立一個權限文件permissions.py中聲明自定義權限類:

from rest_framework.permissions import BasePermission

class IsXiaoMingPermission(BasePermission):
    def has_permission(self, request, view):
        if( request.user.username == "xiaoming" ):
            return True
from .permissions import IsXiaoMingPermission
class StudentViewSet(ModelViewSet):
    queryset = Student.objects.all()
    serializer_class = StudentSerializer
    permission_classes = [IsXiaoMingPermission]

限流Throttling

能夠對接口訪問的頻次進行限制,以減輕服務器壓力。

通常用於付費購買次數,投票等場景使用.

使用

能夠在配置文件中,使用DEFAULT_THROTTLE_CLASSESDEFAULT_THROTTLE_RATES進行全局配置,

REST_FRAMEWORK = {
    'DEFAULT_THROTTLE_CLASSES': (
        'rest_framework.throttling.AnonRateThrottle',
        'rest_framework.throttling.UserRateThrottle'
    ),
    'DEFAULT_THROTTLE_RATES': {
        'anon': '100/day',
        'user': '1000/day'
    }
}

DEFAULT_THROTTLE_RATES 能夠使用 second, minute, hourday來指明週期。

也能夠在具體視圖中經過throttle_classess屬性來配置,如

from rest_framework.throttling import UserRateThrottle
from rest_framework.views import APIView

class ExampleView(APIView):
    throttle_classes = (UserRateThrottle,)
    ...
    pass

可選限流類

1) AnonRateThrottle

限制全部匿名未認證用戶,使用IP區分用戶。

使用DEFAULT_THROTTLE_RATES['anon'] 來設置頻次

2)UserRateThrottle

限制認證用戶,使用User id 來區分。

使用DEFAULT_THROTTLE_RATES['user'] 來設置頻次

3)ScopedRateThrottle

限制用戶對於每一個視圖的訪問頻次,使用ip或user id。

例如:

class ContactListView(APIView):
    throttle_scope = 'contacts'
    ...

class ContactDetailView(APIView):
    throttle_scope = 'contacts'
    ...

class UploadView(APIView):
    throttle_scope = 'uploads'
    ...
REST_FRAMEWORK = {
    'DEFAULT_THROTTLE_CLASSES': (
        'rest_framework.throttling.ScopedRateThrottle',
    ),
    'DEFAULT_THROTTLE_RATES': {
        'contacts': '1000/day',
        'uploads': '20/day'
    }
}

實例

全局配置中設置訪問頻率

'DEFAULT_THROTTLE_RATES': {
        'anon': '3/minute',
        'user': '10/minute'
    }
from rest_framework.authentication import SessionAuthentication
from rest_framework.permissions import IsAuthenticated
from rest_framework.generics import RetrieveAPIView
from rest_framework.throttling import UserRateThrottle

class StudentAPIView(RetrieveAPIView):
    queryset = Student.objects.all()
    serializer_class = StudentSerializer
    authentication_classes = [SessionAuthentication]
    permission_classes = [IsAuthenticated]
    throttle_classes = (UserRateThrottle,)

過濾Filtering

對於列表數據可能須要根據字段進行過濾,咱們能夠經過添加django-fitlter擴展來加強支持。

pip install django-filter

在配置文件中增長過濾後端的設置:

INSTALLED_APPS = [
    ...
    'django_filters',  # 須要註冊應用,
]

REST_FRAMEWORK = {
    ...
    'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',)
}

在視圖中添加filter_fields屬性,指定能夠過濾的字段

class StudentListView(ListAPIView):
    queryset = Student.objects.all()
    serializer_class = StudentSerializer
    filter_fields = ('age', 'sex')

# 127.0.0.1:8000/four/students/?sex=1

排序

對於列表數據,REST framework提供了OrderingFilter過濾器來幫助咱們快速指明數據按照指定字段進行排序。

使用方法:

在類視圖中設置filter_backends,使用rest_framework.filters.OrderingFilter過濾器,REST framework會在請求的查詢字符串參數中檢查是否包含了ordering參數,若是包含了ordering參數,則按照ordering參數指明的排序字段對數據集進行排序。

前端能夠傳遞的ordering參數的可選字段值須要在ordering_fields中指明。

示例:

class StudentListView(ListAPIView):
    queryset = Student.objects.all()
    serializer_class = StudentModelSerializer
    filter_backends = [OrderingFilter]
    ordering_fields = ('id', 'age')

# 127.0.0.1:8000/books/?ordering=-age
# -id 表示針對id字段進行倒序排序
# id  表示針對id字段進行升序排序

若是須要在過濾之後再次進行排序,則須要二者結合!

from rest_framework.generics import ListAPIView
from students.models import Student
from .serializers import StudentModelSerializer
from django_filters.rest_framework import DjangoFilterBackend
class Student3ListView(ListAPIView):
    queryset = Student.objects.all()
    serializer_class = StudentModelSerializer
    filter_fields = ('age', 'sex')
    # 由於局部配置會覆蓋全局配置,因此須要從新把過濾組件核心類再次聲明,
    # 不然過濾功能會失效
    filter_backends = [OrderingFilter,DjangoFilterBackend]
    ordering_fields = ('id', 'age')

分頁Pagination

REST framework提供了分頁的支持。

咱們能夠在配置文件中設置全局的分頁方式,如:

REST_FRAMEWORK = {
    'DEFAULT_PAGINATION_CLASS':  'rest_framework.pagination.PageNumberPagination',
    'PAGE_SIZE': 100  # 每頁數目
}

也可經過自定義Pagination類,來爲視圖添加不一樣分頁行爲。在視圖中經過pagination_clas屬性來指明。

class LargeResultsSetPagination(PageNumberPagination):
    page_size = 1000
    page_size_query_param = 'page_size'
    max_page_size = 10000
class BookDetailView(RetrieveAPIView):
    queryset = BookInfo.objects.all()
    serializer_class = BookInfoSerializer
    pagination_class = LargeResultsSetPagination

注意:若是在視圖內關閉分頁功能,只需在視圖內設置

pagination_class = None

可選分頁器

1) PageNumberPagination

前端訪問網址形式:

GET  http://127.0.0.1:8000/students/?page=4

能夠在子類中定義的屬性:

  • page_size 每頁數目
  • page_query_param 前端發送的頁數關鍵字名,默認爲「page」
  • page_size_query_param 前端發送的每頁數目關鍵字名,默認爲None
  • max_page_size 前端最多能設置的每頁數量
# 聲明分頁的配置類
from rest_framework.pagination import PageNumberPagination
class StandardPageNumberPagination(PageNumberPagination):
    # 默認每一頁顯示的數據量
    page_size = 2
    # 容許客戶端經過get參數來控制每一頁的數據量
    page_size_query_param = "size"
    max_page_size = 10
    # 自定義頁碼的參數名
    page_query_param = "p"

class StudentAPIView(ListAPIView):
    queryset = Student.objects.all()
    serializer_class = StudentModelSerializer
    pagination_class = StandardPageNumberPagination

# 127.0.0.1/four/students/?p=1&size=5

2)LimitOffsetPagination

前端訪問網址形式:

GET http://127.0.0.1/four/students/?limit=100&offset=400

能夠在子類中定義的屬性:

  • default_limit 默認限制,默認值與PAGE_SIZE設置一直
  • limit_query_param limit參數名,默認’limit’
  • offset_query_param offset參數名,默認’offset’
  • max_limit 最大limit限制,默認None
from rest_framework.pagination import LimitOffsetPagination
class StandardLimitOffsetPagination(LimitOffsetPagination):
    # 默認每一頁查詢的數據量,相似上面的page_size
    default_limit = 2
    limit_query_param = "size"
    offset_query_param = "start"

class StudentAPIView(ListAPIView):
    queryset = Student.objects.all()
    serializer_class = StudentModelSerializer
    # 調用頁碼分頁類
    # pagination_class = StandardPageNumberPagination
    # 調用查詢偏移分頁類
    pagination_class = StandardLimitOffsetPagination

異常處理 Exceptions

REST framework提供了異常處理,咱們能夠自定義異常處理函數。

from rest_framework.views import exception_handler

def custom_exception_handler(exc, context):
    # 先調用REST framework默認的異常處理方法得到標準錯誤響應對象
    response = exception_handler(exc, context)

    # 在此處補充自定義的異常處理
    if response is None:
        response.data['status_code'] = response.status_code

    return response

在配置文件中聲明自定義的異常處理

REST_FRAMEWORK = {
    'EXCEPTION_HANDLER': 'my_project.my_app.utils.custom_exception_handler'
}

若是未聲明,會採用默認的方式,以下

rest_frame/settings.py

REST_FRAMEWORK = {
    'EXCEPTION_HANDLER': 'rest_framework.views.exception_handler'
}

例如:

補充上處理關於數據庫的異常

from rest_framework.views import exception_handler as drf_exception_handler
from rest_framework import status
from django.db import DatabaseError

def exception_handler(exc, context):
    response = drf_exception_handler(exc, context)

    if response is None:
        view = context['view']
        if isinstance(exc, DatabaseError):
            print('[%s]: %s' % (view, exc))
            response = Response({'detail': '服務器內部錯誤'}, status=status.HTTP_507_INSUFFICIENT_STORAGE)

    return response

REST framework定義的異常

  • APIException 全部異常的父類
  • ParseError 解析錯誤
  • AuthenticationFailed 認證失敗
  • NotAuthenticated 還沒有認證
  • PermissionDenied 權限決絕
  • NotFound 未找到
  • MethodNotAllowed 請求方式不支持
  • NotAcceptable 要獲取的數據格式不支持
  • Throttled 超過限流次數
  • ValidationError 校驗失敗

也就是說,不少的沒有在上面列出來的異常,就須要咱們在自定義異常中本身處理了。

自動生成接口文檔

REST framework能夠自動幫助咱們生成接口文檔。

接口文檔以網頁的方式呈現。

自動接口文檔能生成的是繼承自APIView及其子類的視圖。

安裝依賴

REST framewrok生成接口文檔須要coreapi庫的支持。

pip install coreapi

設置接口文檔訪問路徑

在總路由中添加接口文檔路徑。

文檔路由對應的視圖配置爲rest_framework.documentation.include_docs_urls

參數title爲接口文檔網站的標題。

from rest_framework.documentation import include_docs_urls

urlpatterns = [
    ...
    path('docs/', include_docs_urls(title='站點頁面標題'))
]

文檔描述說明的定義位置

1) 單一方法的視圖,可直接使用類視圖的文檔字符串,如

class BookListView(generics.ListAPIView):
    """
    返回全部圖書信息.
    """

2)包含多個方法的視圖,在類視圖的文檔字符串中,分開方法定義,如

class BookListCreateView(generics.ListCreateAPIView):
    """
    get:
    返回全部圖書信息.

    post:
    新建圖書.
    """

3)對於視圖集ViewSet,仍在類視圖的文檔字符串中封開定義,可是應使用action名稱區分,如

class BookInfoViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, GenericViewSet):
    """
    list:
    返回圖書列表數據

    retrieve:
    返回圖書詳情數據

    latest:
    返回最新的圖書數據

    read:
    修改圖書的閱讀量
    """

訪問接口文檔網頁

瀏覽器訪問 127.0.0.1:8000/docs/,便可看到自動生成的接口文檔。

接口文档网页

兩點說明:

1) 視圖集ViewSet中的retrieve名稱,在接口文檔網站中叫作read

2)參數的Description須要在模型類或序列化器類的字段中以help_text選項定義,如:

class Student(models.Model):
    ...
    age = models.IntegerField(default=0, verbose_name='年齡', help_text='年齡')
    ...

class StudentSerializer(serializers.ModelSerializer):
    class Meta:
        model = Student
        fields = "__all__"
        extra_kwargs = {
            'age': {
                'required': True,
                'help_text': '年齡'
            }
        }
相關文章
相關標籤/搜索