drf07 過濾 排序 分頁 異常處理 自動生成接口文檔

4. 過濾Filtering

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

pip install django-filter

在配置文件setting.py中增長過濾後端的設置:html

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

 

5. 排序

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

使用方法:git

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

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

示例:django

 
 
INSTALLED_APPS = [
    ...
    'django_filters',  # 須要註冊應用,
]
#全局配置排序過濾器
REST_FRAMEWORK = {
    ...
    'DEFAULT_FILTER_BACKENDS': ('rest_framework.filters.OrderingFilter',),
}
from rest_framework.filters import OrderingFilter
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字段進行升序排序

 

 

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

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

 

6. 分頁Pagination

REST framework提供了分頁的支持。bootstrap

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

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

 

 

 

7. 異常處理 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 = {
    'EXCEPTION_HANDLER': 'my_project.exceptions.custom_exception_handler'
}

 

class APIError(Exception):
    pass

class Student2APIView(APIView):
    def get(self,request,pk):
        try:
            instance = Student.objects.get(pk=pk)
        except Student.DoesNotExist:
            raise APIError("自定義的API錯誤")
            # return Response({"message":"訪問的商品已經下架~"})

        serializer = StudentModelSerializer(instance=instance)
        return Response(serializer.data)
views.py
from rest_framework.response import Response
from rest_framework.views import exception_handler

from four.views import APIError

def custom_exception_handler(exc, context):
    # exc 異常對象
    # context 異常發生時上下文環境

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

    # 在此處補充自定義的異常處理
    if response is None:
        if isinstance(exc,APIError):
            # 記錄錯誤信息,通常記錄到文件中,後頭開發項目時,咱們會使用python的日誌功能記錄
            return Response({"message":"API報錯了"})

    return response
exceptions.py

 

 

8. 自動生成接口文檔

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

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

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

8.1. 安裝依賴

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

pip install coreapi

8.2. 設置接口文檔訪問路徑

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

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

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

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

 

8.3. 文檔描述說明的定義位置

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:
    修改圖書的閱讀量
    """

 

8.4. 訪問接口文檔網頁

瀏覽器訪問 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': '年齡'
            }
        }

 

 

9. Xadmin

xadmin是Django的第三方擴展,比使用Django的admin站點更強大也更方便。

文檔:https://xadmin.readthedocs.io/en/latest/index.html

9.1. 安裝

經過以下命令安裝xadmin的最新版

pip install https://codeload.github.com/sshwsfc/xadmin/zip/django2

在配置文件中註冊以下應用

INSTALLED_APPS = [
  ...
   'xadmin',
   'crispy_forms',
   'reversion',
  ...
]

# 修改使用中文界面
LANGUAGE_CODE = 'zh-Hans'

# 修改時區
TIME_ZONE = 'Asia/Shanghai'

 

xadmin有創建本身的數據庫模型類,須要進行數據庫遷移

python manage.py makemigrations
python manage.py migrate

 

在總路由中添加xadmin的路由信息

import xadmin
xadmin.autodiscover()

# version模塊自動註冊須要版本控制的 Model
from xadmin.plugins import xversion
xversion.register_models()

urlpatterns = [
   path(r'xadmin/', xadmin.site.urls),
]

 

若是以前沒有建立超級用戶,須要建立,若是有了,則能夠直接使用以前的。

python manage.py createsuperuser

 

 

9.2. 使用

  • xadmin再也不使用Django的admin.py,而是須要編寫代碼在adminx.py文件中。

  • xadmin的站點管理類不用繼承admin.ModelAdmin,而是直接繼承object便可。

例如:在子應用中建立adminx.py文件。

站點的全局配置

import xadmin
from xadmin import views

class BaseSetting(object):
   """xadmin的基本配置"""
   enable_themes = True  # 開啓主題切換功能
   use_bootswatch = True

xadmin.site.register(views.BaseAdminView, BaseSetting)

class GlobalSettings(object):
   """xadmin的全局配置"""
   site_title = "路飛學城"  # 設置站點標題
   site_footer = "路飛學城有限公司"  # 設置站點的頁腳
   menu_style = "accordion"  # 設置菜單摺疊

xadmin.site.register(views.CommAdminView, GlobalSettings)

 

站點Model管理

xadmin可使用的頁面樣式控制基本與Django原生的admin一直。

  • list_display 控制列表展現的字段

    list_display = ['id', 'btitle', 'bread', 'bcomment']
  • search_fields 控制能夠經過搜索框搜索的字段名稱,xadmin使用的是模糊查詢

    search_fields = ['id','btitle']
  • list_filter 能夠進行過濾操做的列,對於分類、性別、狀態

    list_filter = ['is_delete']
  • ordering 默認排序的字段

  • show_detail_fields 在列表頁提供快速顯示詳情信息

  • list_editable 在列表頁能夠快速直接編輯的字段

  • refresh_times 指定列表頁的定時刷新

    refresh_times = [5, 10,30,60]  # 設置容許後端管理人員按多長時間(秒)刷新頁面
  • list_export 控制列表頁導出數據的可選格式

    list_export = ('xls', 'xml', 'json')   list_export設置爲None來禁用數據導出功能
    list_export_fields = ('id', 'btitle', 'bpub_date')
  • show_bookmarks 控制是否顯示書籤功能

    show_bookmarks = True
  • data_charts 控制顯示圖表的樣式

    data_charts = {
           "order_amount": {
             'title': '圖書發佈日期表',
             "x-field": "bpub_date",
             "y-field": ('btitle',),
             "order": ('id',)
          },
       #   支持生成多個不一樣的圖表
       #   "order_amount": {
       #     'title': '圖書發佈日期表',
       #     "x-field": "bpub_date",
       #     "y-field": ('btitle',),
       #     "order": ('id',)
       #   },
      }
    • title 控制圖標名稱

    • x-field 控制x軸字段

    • y-field 控制y軸字段,能夠是多個值

    • order 控制默認排序

  • model_icon 控制菜單的圖標【圖標的設置能夠參考bootstrap的圖標css名稱】

    class BookInfoAdmin(object):
      model_icon = 'fa fa-gift'

    xadmin.site.register(models.BookInfo, BookInfodmin)
  • readonly_fields 在編輯頁面的只讀字段

  • exclude 在編輯頁面隱藏的字段

相關文章
相關標籤/搜索