06. Django REST framework - 過濾、排序、異常處理、自動生成接口文檔


過濾Filtering

1 過濾針對於 list,獲取所有(對於列表數據可能需要根據字段進行過濾)
2 在請求路徑中帶過濾條件,對查詢結果進行過濾
# models.py 表模型
from django.db import models

class Book(models.Model):
    name = models.CharField(max_length=34)
    price = models.IntegerField()

# serializer.py 序列化器
from app01 import models
from rest_framework import serializers

class BookModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Book
        fields = "__all__"
        
# urls.py 路由
from django.contrib import admin
from django.urls import path,include
from rest_framework.routers import SimpleRouter
from app01 import views

router = SimpleRouter()
router.register('book',views.BookView)

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

演示准備
演示准備

內置過濾類的使用

復制代碼
1 在視圖類views.py中(必須繼承GenericAPIView)
from app01 import models
from app01 import serializer
from rest_framework.viewsets import ModelViewSet
from rest_framework.filters import SearchFilter # 導入內置過濾類
​
class BookView(ModelViewSet):
    queryset = models.Book.objects.all()
    serializer_class = serializer.BookModelSerializer
    # 配置過濾類(局部使用)
    filter_backends = [SearchFilter,]
    # 配置過濾字段
    search_fields = ['name','price']
    
    
2 瀏覽的地址:
    # 查詢的時候,所有條件都給search,並支持模糊匹配,search可以是name字段,也可以是price
    http://127.0.0.1:8000/book/?search=紅精靈
    http://127.0.0.1:8000/book/?search=11
            
3 全局使用:在settings.py配置文件中配置
REST_FRAMEWORK = {
    'DEFAULT_FILTER_BACKENDS': ('rest_framework.filters.SearchFilter',)
}
復制代碼

 

第三方過濾類使用(django-filter)

內置的SearchFilter過濾類,功能一般,如果你想實現更高級的過濾,自己寫,使用第三方

我們可以通過添加django-fitlter擴展來增強支持。

復制代碼
1 安裝(django:2.2, 3.1, 3.2)
    pip3 install django-filter

Django提示找不到模板django_filters/rest_framework/form.html

此處原因是忘記在INSTALLED_APPS當中注冊app 'django_filters'

只需要在settings.pyINSTALLED_APPS當中加入'django_filters'即可。

INSTALLED_APPS = [
'django_filters'
]
2 在視圖類views.py中(必須繼承GenericAPIView)添加filter_fields屬性,指定可以過濾的字段 from app01 import models from app01 import serializer from rest_framework.viewsets import ModelViewSet from django_filters.rest_framework import DjangoFilterBackend # 導入第三方過濾類 ​ class BookView(ModelViewSet): queryset = models.Book.objects.all() serializer_class = serializer.BookModelSerializer ​ # 使用第三方 # 配置過濾類(局部使用) filter_backends=[DjangoFilterBackend,] # 配置過濾字段 filter_fields=['name','price'] 3 瀏覽的地址: # 查詢可以通過字段查詢,但不支持模糊查詢 http://127.0.0.1:8000/book/?price=11&name=紅精靈 http://127.0.0.1:8000/book/?price=11 4 全局使用:在settings.py配置文件中配置 ​ REST_FRAMEWORK = { 'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',) } ​ # 局部使用(在視圖類中加)
復制代碼

自己定義過濾類

復制代碼
1 寫一個類,繼承第三方過濾類(最好自定義一個py文件,auth.py)
from rest_framework.filters import BaseFilterBackend
class Myfilter(BaseFilterBackend):
    def filter_queryset(self, request, queryset, view):
        name = request.GET.get('name')
        queryset = queryset.filter(name__contains=name)
        return queryset
    
2 在視圖類views.py中配置
from app01 import models
from app01 import serializer
from rest_framework.viewsets import ModelViewSet
from app01.auth import Myfilter # 導入自定義過濾類
class BookView(ModelViewSet):
    queryset = models.Book.objects.all()
    serializer_class = serializer.BookModelSerializer
     ## 自己定義的
    filter_backends = [Myfilter, ]
    
3 瀏覽的地址:支持模糊查詢
    http://127.0.0.1:8000/book/?name=精
    
復制代碼

總結

復制代碼
1 APIViwe中有哪些類屬性
     renderer_classes = api_settings.DEFAULT_RENDERER_CLASSES
    parser_classes = api_settings.DEFAULT_PARSER_CLASSES
    authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES
    throttle_classes = api_settings.DEFAULT_THROTTLE_CLASSES
    permission_classes = api_settings.DEFAULT_PERMISSION_CLASSES
2 GenericAPIView中有哪些類屬性
     filter_backends = api_settings.DEFAULT_FILTER_BACKENDS
    pagination_class = api_settings.DEFAULT_PAGINATION_CLASS
復制代碼

排序

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

使用方法:

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

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

復制代碼
1 在views.py 視圖類中
from app01 import models
from app01 import serializer
from rest_framework.viewsets import ModelViewSet
from rest_framework.filters import OrderingFilter # 導入過濾器排序類
​
class BookView(ModelViewSet):
    queryset = models.Book.objects.all()
    serializer_class = serializer.BookModelSerializer
    ###排序
    # 配置排序類(局部使用)
    filter_backends = [OrderingFilter, ] 
    # 配置排序字段
    ordering_fields=['price','name']
    
    
2 請求方式:(postman中測試)
     http://127.0.0.1:8000/book/?ordering=price  # 默認升序
    http://127.0.0.1:8000/book/?ordering=-price  # 降序
   http://127.0.0.1:8000/book/?ordering=-price,-name # 配多個按,分隔
        
        
3 全局使用:在settings.py 配置文件中配置
REST_FRAMEWORK = {
    'DEFAULT_FILTER_BACKENDS': ('rest_framework.filters.OrderingFilter',),
​
}
復制代碼

 

異常處理 Exceptions

REST framework提供了異常處理,我們可以自定義異常處理函數,不論正常還是異常,通過定制,我們可以返回我們想要返回的樣子

步驟

  1. 自定義函數
  2. 在配置文件中配置函數

注意

如果沒有配置自己處理異常的規則,會執行默認的,如下:

from rest_framework import settings

from rest_framework.views import exception_handler

默認配置流程怎么走?

# 1、 APIView源碼 # dispatch方法源碼 except Exception as exc: response = self.handle_exception(exc) # handle_exception方法源碼 response = exception_handler(exc, context) # 2、views種的exception_handler方法 def exception_handler(exc, context): ··· # 3、 默認配置文件 'EXCEPTION_HANDLER': 'rest_framework.views.exception_handler',

復制代碼

# 在views.py 視圖類中寫一個帶錯誤的視圖類
from rest_framework.views import APIView
​
class TestView(APIView):
    throttle_classes = [MyThrottling, ]
​
    def get(self, request):
        a=[1,3,4]
        # 4/0
        print(a[100])
        return Response('test')
    
# urls.py  路由
from django.urls import path
from app01 import views
​
urlpatterns = [
    path('test/', views.TestView.as_view()),
  
]
復制代碼

REST framework提供了異常處理,我們可以自定義異常處理函數。

復制代碼
1 手動創建一個名為exception的py文件,名字隨意,在文件中寫一個函數
​
from rest_framework.views import exception_handler
from rest_framework.response import Response
​
def custom_exception_handler(exc, context):
    # 先調用REST framework默認的異常處理方法獲得標准錯誤響應對象
    response=exception_handler(exc, context) 
    # 捕獲異常后端窗口信息打印
    print(response) # 只要出錯,這個就是None
    print(exc) # 錯誤信息在exc里
    print(context.get('view')) # 視圖類
    print(context.get('request').get_full_path()) # 當次請求的request對象
    # 在此處補充自定義的異常處理
    if not response: # 更細粒度的對異常做一個區分
        if isinstance(exc,IndexError):
            response=Response({'status':5001,'msg':'越界異常'})
        elif isinstance(exc,ZeroDivisionError):
            response = Response({'status': 5002, 'msg': '越界異常'})
        else:
            response= Response({'status': 5000, 'msg': '沒有權限'})
    # 在這可以記錄日志:一旦出錯就記錄日志
    return response
​
2 在settings.py 配置文件中配置
REST_FRAMEWORK = {
    'EXCEPTION_HANDLER':'app01.excepiton.custom_exception_handler',
}
3 以后只要視圖中執行出了錯誤,就會捕獲異常,記錄日志,並返回統一的格式給前端

或者:

源碼exception_handler方法有兩種情況,if判斷第一種情況是處理了APIException對象的異常返回Reponse對象,第二種情況是處理了其他異常返回了None,這里我們針對這兩種情況的異常進行定制處理

  • exc:錯誤原因
  • context:字典,包含了當前請求對象和視圖類對象

自定義異常處理方法

from rest_framework.views import exception_handler from rest_framework.response import Response def myexception_handler(exc, context): # 先執行原來的exception_handler幫助我們處理 res = exception_handler(exc, context) if res: # res有值代表處理過了APIException對象的異常了,返回的數據再定制 res = Response(data={'code': 998, 'msg': res.data.get('detail', '服務器異常,請聯系系統管理員')}) # res = Response(data={'code': 998, 'msg': '服務器異常,請聯系系統管理員'}) # res.data.get從響應中獲取原來的處理詳細信息 else: res = Response(data={'code': 999, 'msg': str(exc)}) print(exc) # list index out of range '''模擬日志處理''' request = context.get('request') # 當次請求的request對象 view = context.get('view') # 當次執行的視圖類對象 print('錯誤原因:%s,錯誤視圖類:%s,請求地址:%s,請求方式:%s' % (str(exc), str(view), request.path, request.method)) '''結果: 錯誤原因:list index out of range,錯誤視圖類:<app01.views.TestView object at 0x000001C3B1C7CA58>,請求地址:/test/,請求方式:GET ''' return res
復制代碼

配置文件


REST_FRAMEWORK = { 'EXCEPTION_HANDLER': 'app01.exception.myexception_handler' # 再出異常,會執行自己定義的函數 }

REST framework定義的異常

  • APIException 所有異常的父類

  • ParseError 解析錯誤

  • AuthenticationFailed 認證失敗

  • NotAuthenticated 尚未認證

  • PermissionDenied 權限決絕

  • NotFound 未找到

  • MethodNotAllowed 請求方式不支持

  • NotAcceptable 要獲取的數據格式不支持

  • Throttled 超過限流次數

  • ValidationError 校驗失敗

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

自動生成接口文檔

REST framework可以自動幫助我們生成接口文檔。

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

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

復制代碼
接口文檔 coreapi,swagger
​
安裝依賴:REST framewrok生成接口文檔需要coreapi庫的支持。
    pip3 install coreapi
 
使用步驟:
​
1 在urls.py 路由中
    from rest_framework.documentation import include_docs_urls
​
    urlpatterns = [
     path('doc/', include_docs_urls(title='圖書管理項目接口文檔')),
    ]
    
2 在settings.py 配置文件中
    REST_FRAMEWORK = {
    'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema',
    }
    
3 在view.py 視圖類中對應的方法上加注釋即可
    
4 如果是ModelViewSet
   from app01 import models
    from app01 import serializer
    from rest_framework.viewsets import ModelViewSet
    from rest_framework.filters import OrderingFilter
​
class BookView(ModelViewSet):
    """
      list:
      返回圖書列表數據,通過Ordering字段排序
​
      retrieve:
      返回圖書詳情數據
​
      latest:
      返回最新的圖書數據
​
      read:
      查詢單個圖書接口
    """
    queryset = models.Book.objects.all()
    serializer_class = serializer.BookModelSerializer
    # 排序
    filter_backends = [OrderingFilter,]
    ordering_fields = ['price','name']
    
    
5 字段描述,寫在models.py的help_text上
from django.db import models
​
class Book(models.Model):
    name = models.CharField(max_length=34,help_text='名字字段,字符串')
    price = models.IntegerField(help_text='價格字段,整型')
​
6 瀏覽的地址(瀏覽器中)
    http://127.0.0.1:8000/doc/
            
# 如果繼承的是其它視圖類,直接在對應的def函數下面寫注釋即可,例:
class BookView(APIView):
    def get(self, request):
        """
        所有圖書信息
        :param request: 
        :return: 
        """
        res = models.Book.objects.all()
        ser = serializer.BookModelSerializer(instance=res, many=True)
        return Response(ser.data)
復制代碼

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM