1. 程式人生 > 實用技巧 >drf ( 學習第四部 )

drf ( 學習第四部 )

目錄

DRF框架中常用的元件

分頁Pagination

異常處理Exceptions

自動生成介面文件

  安裝依賴

  設定介面文件訪問路徑

  訪問介面文件網頁

Admin

  列表頁配置

  詳情頁配置

Xadmin

  安裝

  使用

    站點的全域性配置

    站點Model管理

DRF框架中常用的元件

分頁Pagination

REST framework 提供了分頁的支援. 我們可以在配置檔案中設定全域性的分頁方式,如:

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

如果在配置settings.py檔案中, 設定了全域性分頁,那麼在drf中凡是呼叫了ListModelMixin的list(),都會自動分頁。如果專案中出現大量需要分頁的資料,只有少數部分介面不需要分頁,則可以在少部分的檢視類中關閉分頁功能。

class 檢視類(ListAPIView):
    pagination_class = None

也可以通過自定義P阿覅nation類 ,來為檢視新增不同分頁行為. 在檢視中通過 pagination_class屬性來指明.

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

可選分頁器

! ) PagiNumberPagination

前端訪問網址形式:

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 ) LinitOffsetPagination

前端訪問網址形式:

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

可以在子類中定義的屬性:

default預設限制, 預設值與 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 提供了自定義異常處理, 我們可以自定義的方式來編寫異常處理函式. 例如我們想要在要建立一個自定義異常函式.

這個函式, 我們儲存到當前主應用中( 注意在實際工作中, 我們可以設定一個單獨的獨立的公共目錄來儲存這種公共的函式/工具/類庫 ) .

drfemo/exceptions.py, 程式碼:

"""自定義異常"""
# drf內建的異常處理,僅僅針對於API介面進行異常處理,不是api出錯,則不識別,不處理
from rest_framework.views import exception_handler as drf_exception_handler
from django.db import DatabaseError
from rest_framework.response import Response
from rest_framework import status
from django.core.exceptions import ImproperlyConfigured
def custom_exception_handler(exc,context):
    """
    自定義異常處理函式
    :param exc: 異常物件,本次發生的異常物件
    :param context: 字典,異常出現時的執行上下文環境
    :return:
    """
    # 返回值要麼是報錯的響應資訊,要麼就是None
    response = drf_exception_handler(exc,context)

    if response is None:
        if isinstance(exc, DatabaseError):
            # 資料庫異常
            # 一般先進行日誌的記錄
            # 然後才返回給客戶端
            response = Response({"detail":"資料庫異常"}, status=status.HTTP_507_INSUFFICIENT_STORAGE)

        # 其他的異常處理
        if isinstance(exc, Exception):
            response = Response({"detail":"資料訪問出錯"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

    return response

在主應用的配置檔案settings.py 中宣告自定義的異常處理

REST_FRAMEWORK = {
    # 異常處理
    'EXCEPTION_HANDLER': 'drfdemo.exceptions.custom_exception_handler',
}

如果未宣告, 會採用預設的方式, 如下:
rest_framework/settings.py

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

REST framework 定義的異常

  • APIException drf中所有異常的父類

  • ParseError 解析錯誤

  • AuthenticationFailed 認證失敗

  • NotAuthenticated 尚未認證

  • PermissionDenied 許可權受限

  • NotFound 未找到

  • MethodNotAllowed 請求方式不支援

  • NotAcceptable 要獲取的資料格式不支援

  • Throttled 超過限流次數

  • ValidationError 校驗失敗

也就是說, 很多的沒有在上面列出來的異常,就需要我們在自定義異常中子處理了.

自動生成介面文件

官方文件:http://core-api.github.io/python-client/

REST framework可以自動幫助我們生成介面文件。

介面文件以網頁的方式呈現。

自動介面文件能生成的是繼承自APIView及其子類的檢視。

  安裝依賴

REST framework 生成介面文件需要 core挨批 庫的支援

pip install coreapi

  設定介面文件訪問路徑

在settings.py中配置介面文件

REST_FRAMEWORK = {
    # 。。。 其他選項
    # 介面文件
    'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.AutoSchema',
}

在總路由中新增介面文件路徑.

文件路由對應的檢視配置為:
`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': '年齡'
            }
        }

Admin

django內建了一個強大的元件叫Admin, 提供給網站管理員快速開發運營後臺的管理站點.

站點文件:https://docs.djangoproject.com/zh-hans/2.2/ref/contrib/admin/

輔助文件:https://www.runoob.com/django/django-admin-manage-tool.html

注意:要使用Admin,必須先建立超級管理員.   python manage.py createsuperuser

訪問地址:http://127.0.0.1:8000/admin,訪問效果如下:

admin 站點預設並沒有提供其他的操作給我們,所以一切功能都需要我們進行配置, 在專案中,我們每次建立子應用的時候都會存在一個admin,朋友檔案. 這個檔案就是用於配置admin站點功能的檔案.

admin, py 裡面允許我們編寫的程式碼一共可以分成2部分:

  列表頁配置

主要用於針對專案中各個子應用裡面的model.py裡面的模型, 根據這些模型自動生成後臺運營站點的管理功能.

from django.contrib import admin
from .models import Student
class StudentModelAdmin(admin.ModelAdmin):
    """學生模型管理類"""
    pass

# admin.site.register(模型類, 模型管理類)
admin.site.register(Student, StudentModelAdmin)

關於列表的配置嗎程式碼:

from django.contrib import admin
from .models import Student
class StudentModelAdmin(admin.ModelAdmin):
    """學生模型管理類"""
    date_hierarchy = 'born' # 按指定時間欄位的不同值來進行選項排列
    list_display = ['id', "name", "sex", "age", "class_num","born","my_born"] # 設定列表頁的展示欄位
    ordering = ['-id']  # 設定預設排序欄位,欄位前面加上-號表示倒敘排列
    actions_on_bottom = True  # 下方控制欄是否顯示,預設False表示隱藏
    actions_on_top = True  # 上方控制欄是否顯示,預設False表示隱藏
    list_filter = ["class_num"]  # 過濾器,按指定欄位的不同值來進行展示
    search_fields = ["name"]  # 搜尋內容

    def my_born(self,obj):
        return str(obj.born).split(" ")[0]

    my_born.short_description = "出生日期"  # 自定義欄位的描述資訊
    my_born.admin_order_field = "born"     # 自定義欄位點選時使用哪個欄位作為排序條件

# admin.site.register(模型類, 模型管理類)
admin.site.register(Student, StudentModelAdmin)

  詳情頁配置

from django.contrib import admin
from .models import Student
class StudentModelAdmin(admin.ModelAdmin):
    """學生模型管理類"""
    date_hierarchy = 'born' # 按指定時間欄位的不同值來進行選項排列
    list_display = ['id', "name", "sex", "age", "class_null","born","my_born"] # 設定列表頁的展示欄位
    ordering = ['-id']  # 設定預設排序欄位,欄位前面加上-號表示倒敘排列
    actions_on_bottom = True  # 下方控制欄是否顯示,預設False表示隱藏
    actions_on_top = True  # 上方控制欄是否顯示,預設False表示隱藏
    list_filter = ["class_null"]  # 過濾器,按指定欄位的不同值來進行展示
    search_fields = ["name"]  # 搜尋內容

    def my_born(self,obj):
        return str(obj.born).split(" ")[0]

    my_born.short_description = "出生日期"  # 自定義欄位的描述資訊
    my_born.admin_order_field = "born"     # 自定義欄位點選時使用哪個欄位作為排序條件

    def delete_model(self, request, obj):
        """當站點刪除當前模型時執行的鉤子方法"""
        print("有人刪除了模型資訊[新增/修改]")

        # raise Exception("無法刪除") # 阻止刪除
        return super().delete_model(request, obj) # 繼續刪除

    def save_model(self, request, obj, form, change):
        """
        當站點儲存當前模型時
        """
        print("有人修改了模型資訊[新增/修改]")
        # 區分新增和修改? obj是否有id
        print(obj.id)
        return super().save_model(request, obj, form, change)

    # fields = ('name', 'age', 'class_null', "description")  # exclude 作用與fields相反
    # readonly_fields = ["name"]  # 設定只讀欄位

    # 欄位集,fieldsets和fields只能使用其中之一
    fieldsets = (
        ("必填項", {
            'fields': ('name', 'age', 'sex')
        }),
        ('可選項', {
            'classes': ('collapse',),  # 摺疊樣式
            'fields': ('class_null', 'description'),
        }),
    )


# admin.site.register(模型類, 模型管理類)
admin.site.register(Student, StudentModelAdmin)

Xadmin

下點敏是Django 的第三方擴充套件, 是一個比Django的admin站點使用更方便的後臺站點,.構建於admin站點之上.

文件:http://sshwsfc.github.io/xadmin/

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

  安裝

通過如下命令安裝xadmin的最新版

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

在配置檔案settings.py中註冊如下應用:

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('xadmin/', xadmin.site.urls),
]

建立超級使用者

python manage.py createsuperuser

  使用

  • xadmin不用使用Django的admin.py 進行功能配置樂樂, 而是需要編寫程式碼在admin.py檔案中.
  • xadmin的站點管理類不用繼承 admin.ModelAdmin, 而是直接繼承 object 即可

例如: 在子應用 students 中建立 admin.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', 'title', 'read', 'comment']

  • search_fields控制可以通過搜尋框搜尋的欄位名稱, xadmin使用的是模糊查詢
    • search_fields = ['id','title']

  • list_filter 可以進行過濾操作的列, 對於分類, 性別,狀態
    • list_filter = ['is_delete']

  • ordering預設排序的欄位
  • readonly_fields在編輯頁面的只讀欄位
  • exclude 在編輯頁面隱藏的欄位
  • list_editable 在列表頁可以快速直接編寫的欄位
  • show_detail_fields 在列表頁提供快速顯示詳情資訊
  • refresh_times 指定列表頁的定時重新整理
    • refresh_times = [5, 10,30,60]  # 設定允許後端管理人員按多長時間(秒)重新整理頁面

  • list_export 控制列表匯出資料的可選格式
    • list_export = ('xls', 'xml', 'json')   list_export設定為None來禁用資料匯出功能
      list_export_fields = ('id', 'title', 'pub_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 控制選單的圖示

這裡使用的圖示是來自 bootstrap3 的圖示.https://v3.bootcss.com/components/

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

xadmin.site.register(models.BookInfo, BookInfodmin)

修改admin或者下低敏站點下的子應用成中文內容.

# 在子應用的apps.py下面的配置中,新增一個屬性verbose_name
from django.apps import AppConfig

class StudentsConfig(AppConfig):
    name = 'students'
    verbose_name = "學生管理"


# 然後在當前子應用的__init__.py裡面新增一下程式碼:
default_app_config = "students.apps.StudentsConfig"