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.py的INSTALLED_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提供了異常處理,我們可以自定義異常處理函數,不論正常還是異常,通過定制,我們可以返回我們想要返回的樣子
步驟
- 自定義函數
- 在配置文件中配置函數
注意
如果沒有配置自己處理異常的規則,會執行默認的,如下:
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 未找到
-
-
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)


