rest_framework框架的認識

 

rest_framework框架的認識

 
  
它是基於Django的,幫助咱們快速開發符合RESTful規範的接口框架。

一  路由

  能夠經過路由as_view()傳參 根據請求方式的不一樣執行對應不一樣的方法python

  在routers模塊下 封裝了不少關於路由的方法 , 最基礎的BaseRouter類,給我提供自定製的接口。數據庫

  下面這個方法給咱們提供了自動生成兩條帶參數的urldjango

 
from rest_framework import routers
from django.conf.urls import url, include
from course.models import Course
from course.views import CourseView

routers = routers.DefaultRouter()
routers.register('Course', CourseView)

urlpatterns = [
    url(r'^', include(routers.urls)),

]
 

二  視圖

  幫助開發者提供了一些類,並在類中提供了多種方法供咱們使用,下圖是提供的主要的類以及繼承關係。api

   提供其餘一些視圖函數類,能夠去源碼裏看。瀏覽器

三   版本控制

  下面以URL上控制版本爲例app

  一、添加配置框架

 
REST_FRAMEWORK = {
    # 默認使用的版本控制類
    'DEFAULT_VERSIONING_CLASS': 'rest_framework.versioning.URLPathVersioning',
    # 容許的版本
    'ALLOWED_VERSIONS': ['v1', 'v2'],
    # 版本使用的參數名稱
    'VERSION_PARAM': 'version',
    # 默認使用的版本
    'DEFAULT_VERSION': 'v1',
}

  二、設置路由函數

urlpatterns = [
    #url(r'^admin/', admin.site.urls),
        url(r'^api/(?P<version>\w+)/', include('api.urls')),
]

  三、獲取版本post

    request.version ui

四   認證

  rest_framework給咱們提供了認證的接口,由BaseAuthentication類提供接口,也有一些封裝好的認證類(請走入源碼....)

  接口函數 authticate  認證成功返回一元組(user,token)分別賦值給request.user  和 request.auth

  下面是一個簡單的認證示例

 
class Auth(BaseAuthentication):
    def authenticate(self, request):
        token = request.query_params.get('token')
        obj = models.Token.objects.filter(token=token).first()
        if not obj:
            raise AuthenticationFailed({'code': 1001, 'error': '認證失敗'})
        return (obj.user.username, obj)
 

  咱們的認證類能夠放在局部視圖函數,也能夠配置爲全局認證。

# 局部視圖函數認證
class MyView(APIView):
    authentication_classes = [Auth]
    pass
# 全局配置 在settings.py
REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [Auth],
}

五  權限

  由BasePermission類給我提供接口 接口函數爲 has_permission  以及 has_object_permission

  有權限返回True 沒有則返回False,默認的權限類爲下圖。

 
# 容許任何人訪問
class AllowAny(BasePermission):
    """
    Allow any access.
    This isn't strictly required, since you could use an empty
    permission_classes list, but it's useful because it makes the intention
    more explicit.
    """

    def has_permission(self, request, view):
        return True
 

  接口類爲下圖

 
class BasePermission(object):
    """
    A base class from which all permission classes should inherit.
    """

    def has_permission(self, request, view):
        """
        Return `True` if permission is granted, `False` otherwise.
        """
        # 這裏寫咱們的權限邏輯
        return True

    def has_object_permission(self, request, view, obj):
        """
        Return `True` if permission is granted, `False` otherwise.
        """
        return True
 

  還封裝了一些權限類,只容許admin用戶訪問的權限,只給認證的用戶權限等等,請走源碼........

六  頻率

  基礎的BaseThrottle類提供接口 接口函數爲 allow_request,若是返回False則走wait

  SimpleRateThrottle類給咱們提供了get_cache_key接口,繼承這個類要寫rate(num_request, duration)多長時間內訪問次數

  實現原理以下代碼:

 
class SimpleRateThrottle(BaseThrottle):
    def allow_request(self, request, view):
        if self.rate is None:
            return True

        self.key = self.get_cache_key(request, view)
        if self.key is None:
            return True

        self.history = self.cache.get(self.key, [])
        self.now = self.timer()

       # 原理的實現邏輯
        while self.history and self.history[-1] <= self.now -self.duration:
            self.history.pop()
        if len(self.history) >= self.num_requests:
            return self.throttle_failure()
        return self.throttle_success()
 

  這裏就放這些~~具體~請你們走入源碼.......

七   序列化

  對queryset序列化以及對請求數據格式驗證。

  一般繼承兩個類 Serializer 以及 ModelSerializer  

  Serializer 序列化的每一個字段都要本身寫  ModelSerializer 會根據數據庫表渲染全部字段 

  注意sourse 以及 鉤子函數的應用 代碼以下:

 
class CourseDetailModelSerializers(serializers.ModelSerializer):
    title = serializers.CharField(source='course.name')
    img = serializers.ImageField(source='course.course_img')
    level = serializers.CharField(source='course.get_level_display')
    recommends = serializers.SerializerMethodField()
    chapters = serializers.SerializerMethodField()

    def get_recommends(self, obj):
        queryset = obj.recommend_courses.all()
        return [{'id': row.id, 'title': row.name} for row in queryset]

    def get_chapters(self, obj):
        queryset = obj.course.course_chapters.all()
        return [{'id': row.id, 'name': row.name} for row in queryset]

    class Meta:
        model = CourseDetail
        fields = ['course', 'title', 'img', 'level', 'why_study', 'chapters', 'recommends']
 

 

八   分頁

  對從數據庫中獲取到的數據進行分頁處理  SQL --> limit  offset

    - 根據頁碼:http://www.myclass.com/api/v1/student/?page=1&size=10

    - 根據索引:http://www.myclass.com/api/v1/student/?offset=60&limit=10

    - 根據遊標:http://www.myclass.com/api/v1/student/?page=erd8

  頁碼越大速度越慢,爲何怎麼解決?

    - 緣由:頁碼越大向後須要掃描的行數越多,由於每次都是從0開始掃描

    - 解決:

      - 限制當前顯示的頁數

      - 記錄當前頁面數據ID的最大值和最小值,再次分頁時,根據ID進行篩選,在分頁

  rest_framework 分頁的配置

    -  全局分頁配置  

# settings.py 
REST_FRAMEWORK = {
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
    'PAGE_SIZE': 100
}

    -  修改分頁風格

 
class MyPagination(PageNumberPagination):
    page_size = 100
    page_size_query_param = 'page_size'
    max_page_size = 1000

# 而後在視圖中使用.pagination_class屬性調用該自定義類
class MyView(generics.ListAPIView):
    queryset = Billing.objects.all()
    serializer_class = BillingRecordsSerializer
    pagination_class = MyPagination

# 或者是在settings.py中修改DEFAULT_PAGINATION_CLASS

REST_FRAMEWORK = {
    'DEFAULT_PAGINATION_CLASS': 'apps.core.pagination.MyPagination'
}
 

  rest_framework給我提供的API

    一、 PageNumberPagination

1
GET https: / / api.example.org / accounts / ?page = 4

    響應對象 

 
HTTP 200 OK
{
    "count": 1023
    "next": "https://api.example.org/accounts/?page=5",
    "previous": "https://api.example.org/accounts/?page=3",
    "results": [
       …
    ]
}
 

   配置屬性

    - page_size  每頁顯示對象的數量 若是設置了就重寫PAGE_SIZE  

    - page_query_param  頁面查詢參數 指示分頁空間的查詢參數的名字

    - page_size_query_param  容許客戶端根據每一個請求設置頁面大小 通常都爲None

    - max_page_size  設置了page_size_query_param 纔有意義 客戶端請求頁面中顯示最大數量

    - last_page_strings 儲存page_query_param參數請求過的值列表或元組

  二、LImitOffsetPagination

    路由配置以及返回類型

 
GET https://api.example.org/accounts/?limit=100&offset=400

HTTP 200 OK
{
    "count": 1023
    "next": "https://api.example.org/accounts/?limit=100&offset=500",
    "previous": "https://api.example.org/accounts/?limit=100&offset=300",
    "results": [
       …
    ]
}
 

   配置參數

    - page_size  每頁顯示對象的數量 若是設置了就重寫PAGE_SIZE

    - default_limit: 若是客戶端沒有提供,則默認使用與PAGE_SIZE值同樣。 

    - limit_query_param:表示限制查詢參數的名字,默認爲’limit’ 

    - offset_query_param:表示偏移參數的名字, 默認爲’offset’ 

    - max_limit:容許頁面中顯示的最大數量,默認爲None 

  三、CursorPagination

    - 基於遊標的分頁顯示了一個不透明的「cursor」指示器,客戶端能夠使用它來瀏覽結果集。

    - 這種分頁方式只容許用戶向前或向後進行查詢。而且不容許客戶端導航到任意位置。

    - 基於遊標的分頁方式比較複雜,它要求結果集給出一個固定的順序,而且不容許客戶端任意的對結果集進行索引

    全局配置以下

REST_FRAMEWORK = {
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.CursorPagination',
    'PAGE_SIZE': 100
}

    配置參數:

      - page_size:顯示的最大條數 

      - cursor_query_param: 遊標查詢參數名,默認爲’cursor’ 

      - ordering: 排序字段名的列表或者元組,例如ordering = ‘slug’,默認爲-created 

  四、自定義分頁

    - 繼承pagination.BasePagination

    - 重寫paginate_queryset(self, queryset, request, view=None)方法 ,

      初始化queryset對象,設置pagination實例  返回一個包含用戶請求內容的可迭代對象 造成分頁對象

    - 重寫get_paginated_response(self, data)方法

      序列化請求頁中所包含的對象,返回一個Response對象

 
class CustomPagination(pagination.PageNumberPagination):
    def get_paginated_response(self, data):
        return Response({
            'links': {
               'next': self.get_next_link(),
               'previous': self.get_previous_link()
            },
            'count': self.page.paginator.count,
            'results': data
        })

# 設置自定義分頁、
REST_FRAMEWORK = {
    'DEFAULT_PAGINATION_CLASS': 'my_project.apps.core.pagination.CustomPagination',
    'PAGE_SIZE': 100
}
 

九  解析器

  默認的三個解析器 

    - JsonParser  Json數據解析器

    -  FormParser 和 MultiPartParser 通常同時使用

      Both request.data will be populated with a QueryDict. 官方文檔的解釋

 
DEFAULTS = {
    # rest_framework  settings.py
    'DEFAULT_PARSER_CLASSES': (
        'rest_framework.parsers.JSONParser',
        'rest_framework.parsers.FormParser',
        'rest_framework.parsers.MultiPartParser'
    ),
}
 

 

十   渲染器

  默認的兩個渲染器,一個是Json的,一個是用瀏覽器訪問rest_framework自帶的模板的

 
DEFAULTS = {
    # rest_framework   setting.py
    'DEFAULT_RENDERER_CLASSES': (
        'rest_framework.renderers.JSONRenderer',
        'rest_framework.renderers.BrowsableAPIRenderer',
    ),
}
相關文章
相關標籤/搜索