視圖集ViewSet
視圖集的繼承關(guān)系

視圖集類繼承關(guān)系.png
兩個基本視圖集
| 視圖集 | 繼承自 |
|---|---|
| Viewset | APIView,ViewSetMixin |
| GenricViewset | GenericAPIView,ViewSetMixin |
- ViewSet
- 在ViewSet中,沒有提供任何動作action方法,需自己實現(xiàn)動作action( list() 、create() 等)
- 因為繼承自ViewSetMixin,實現(xiàn)了將請求方式和action動作在as_view中進(jìn)行映射,鍵值對中,值可以相同,鍵必須不同
as_view({'請求方式1':'action動作1','請求方式2':'action動作2',})
- GenricViewSet
class BooksViewSet(ViewSet):
def list(self, request):
#獲取所有數(shù)據(jù)
books = BookInfo.objects.all()
ser = BookSerializers(books, many=True)
return Response(ser.data)
def create(self, request):
#保存數(shù)據(jù)
data = request.data
ser = BookSerializers(data=data)
ser.is_valid(raise_exception=True)
ser.save()
return Response(ser.data)
def last(self, request):
#返回最后一本圖書信息
book = BookInfo.objects.last()
ser = BookSerializers(book)
return Response(ser.data)
def show(self, request, pk):
#獲取指定數(shù)據(jù)
book = BookInfo.objects.get(id=pk)
ser = BookSerializers(book)
return Response(ser.data)
兩個擴(kuò)展視圖集
| 擴(kuò)展視圖集 | 繼承自 |
|---|---|
| ModelViewset | GenricViewset,五個擴(kuò)展類 |
| ReadOnlyModelViewSet | GenricViewset,ListModelMixin,RetrieveModelMixin |
- ModelViewset
- 繼承自GenericAPIVIew、ListModelMixin、RetrieveModelMixin、CreateModelMixin、UpdateModelMixin、DestoryModelMixin
- ReadOnlyModelViewSet
- 參與序列化返回,所以繼承自查詢單個數(shù)據(jù)和查詢所有數(shù)據(jù)的擴(kuò)展類
#定義一個分頁
class PageNum(PageNumberPagination):
page_size_query_param = 'page_size' #指定控制頁面展示數(shù)量的參數(shù)
max_page_size = 8 #最大返回多少條數(shù)據(jù)
class BooksModelViewSet(ModelViewSet):
serializer_class = BookSerializers
queryset = BookInfo.objects.all()
#局部認(rèn)證屬性
# authentication_classes = [BasicAuthentication, SessionAuthentication]
#局部權(quán)限屬性
# permission_classes = [IsAuthenticated]
#局部限流屬性
# throttle_classes = [UserRateThrottle]
#對視圖進(jìn)行限流命名, 在setting.py中進(jìn)行限流次數(shù)的指定
# throttle_scope = 'shows'
#過濾字段指定
# filter_fields = ('btitle', 'bread')
# #排序過濾
# #指定過濾的類方法
# filter_backends = [OrderingFilter]
# #針對排序的字段定義
# ordering_fields = ['id', 'bread']
#局部配置 分頁屬性
# pagination_class = PageNum
@action(methods=['get'], detail=True)
def show(self, request, pk):
#手動拋出一個異常
# raise DataError
#獲取指定數(shù)據(jù)
book = self.get_object()
ser = self.get_serializer(book)
return Response(ser.data)
視圖集自定義action動作
在視圖集中,除了默認(rèn)的動作(list() 提供一組數(shù)據(jù),retrieve() 提供單個數(shù)據(jù),create() 創(chuàng)建數(shù)據(jù),update() 保存數(shù)據(jù),destory() 刪除數(shù)據(jù))外,可以自定義動作
- 添加自定義動作時,需要rest_framework.decorators.action裝飾器
- 在自定義動作方法上,添加@action(),接收兩個參數(shù)
- methods,該action支持的請求方式,列表傳遞
- detail,action中要處理的是否是視圖資源的對象(即是否通過url路徑獲取主鍵)
- True 表示使用通過URL獲取的主鍵對應(yīng)的數(shù)據(jù)對象
- False 表示不使用URL獲取主鍵
路由Router
SimpleRouter
- 創(chuàng)建router,并注冊視圖集
- register(prefix, viewset, base_name)
- prefix 該視圖集的路由前綴
- viewset 視圖集
- base_name 路由名稱的前綴
from rest_framework import routers
router = routers.SimpleRouter()
router.register(r'books', BookInfoViewSet, base_name='book')
- 添加路由數(shù)據(jù)
- 在注冊之后,urlpatterns += router.urls
- 直接在urlpatterns中includerouter.url
- url(r'^', include(router.urls))
- 視圖集中使用裝飾器@action,在視圖類內(nèi)自定義的方法上添加自動生成路由
- @action(methods=['get'], detail=False)
- detail為False,生成的路由中不會有正則匹配(方法中不接收參數(shù))
- detail為True,生成的路由中有正則匹配(方法中接收參數(shù))
DefaultRouter
DefaultRouter會多附帶一個默認(rèn)的API根視圖,返回一個包含所有列表視圖的超鏈接響應(yīng)數(shù)據(jù)
因為視圖集繼承自ViewSetMixin,才有action屬性,裝飾器和自動生成路由的方法
認(rèn)證,權(quán)限和限流屬性(APIView)
- authentication_classes認(rèn)證屬性
- 全局認(rèn)證,在settings.py的REST_FRAMEWORK中定義 'DEFAULT_AUTHENTICATION_CLASSES'
- 局部認(rèn)證,在類視圖中定義authentication_classes = (SessionAuthentication, BasicAuthentication)
- permission_classes 權(quán)限認(rèn)證
- 權(quán)限控制可以限制用戶對于視圖的訪問和對于具體數(shù)據(jù)對象的訪問
- 在執(zhí)行視圖的dispatch()方法前,會先進(jìn)行視圖訪問權(quán)限的判斷
- 在通過get_object()獲取具體對象時,會進(jìn)行對象訪問權(quán)限的判斷
- 提供的權(quán)限
- AllowAny 允許所有用戶
- IsAuthenticated 僅通過認(rèn)證的用戶
- IsAdminUser 僅管理員用戶
- IsAuthenticatedOrReadOnly 認(rèn)證的用戶可以完全操作,否則只能get讀取
- 全局配置,在settings.py的REST_FRAMEWORK中定義 'DEFAULT_PERMISSION_CLASSES',
- 局部配置,在類視圖中定義permission_classes = (IsAuthenticated,)
- 權(quán)限控制可以限制用戶對于視圖的訪問和對于具體數(shù)據(jù)對象的訪問
- throttle_classes限流屬性
- 全局配置,在settings.py的REST_FRAMEWORK中定義DEFAULT_THROTTLE_CLASSES (限流類)和 DEFAULT_THROTTLE_RATES(限流周期)
- 可選限流類
- AnonRateThrottle,限制所有匿名未認(rèn)證用戶,DEFAULT_THROTTLE_RATES['anon'] 來設(shè)置頻次
- UserRateThrottle,限制認(rèn)證用戶,DEFAULT_THROTTLE_RATES['user'] 來設(shè)置頻次
- ScopedRateThrottle,限制用戶對于每個視圖的訪問頻次,在視圖類中用throttle_scope起別名,在settings.py中對別名進(jìn)行頻次設(shè)置
- 可選限流類
- 局部配置,在類視圖中定義throttle_classess=(UserRateThrottle,)
- 全局配置,在settings.py的REST_FRAMEWORK中定義DEFAULT_THROTTLE_CLASSES (限流類)和 DEFAULT_THROTTLE_RATES(限流周期)
過濾與排序?qū)傩?/h3>
- 過濾
- 安裝django-filter
pip insall django-filter
- 將django-filter在settings.py中注冊應(yīng)用
- 在settings.py中的REST_FRAMEWORK,定義'DEFAULT_FILTER_BACKENDS'
- 在視圖中添加filter_fields屬性,指定可以過濾的字段
- 在瀏覽器進(jìn)行訪問時,?字段=查詢內(nèi)容
- 排序
- 在試圖類中設(shè)置filter_backends,使用rest_framework.filters.OrderingFilter過濾器,REST framework會在請求的查詢字符串參數(shù)中檢查是否包含了ordering參數(shù),如果包含了ordering參數(shù),則按照ordering參數(shù)指明的排序字段對數(shù)據(jù)集進(jìn)行排序。
- 前端可以傳遞的ordering參數(shù)的可選字段值需要在ordering_fields中指明。
- 不用在settings.py中做任何配置
- 瀏覽器訪問時,通過?ordering=字段,從小到大,-字段,從大到小
filter_backends = [OrderingFilter]
ordering_fields = ('id', 'bread', 'bpub_date')
- 過濾和排序不能同時使用
分頁,異常處理和自動生成接口文檔
- 分頁
- 全局配置
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 100 # 每頁數(shù)目
}
- 局部配置
-自定義Pagination類,為視圖添加分頁行為
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
- 可選分頁器
- PageNumberPagination
- 前端訪問:GET http://api.example.org/books/?page=4
- 在子類中定義的屬性
page_size 每頁數(shù)目
page_query_param 前端發(fā)送的頁數(shù)關(guān)鍵字名,默認(rèn)為"page"
page_size_query_param 前端發(fā)送的每頁數(shù)目關(guān)鍵字名,默認(rèn)為None
max_page_size 前端最多能設(shè)置的每頁數(shù)量
from rest_framework.pagination import PageNumberPagination
class StandardPageNumberPagination(PageNumberPagination):
page_size_query_param = 'page_size'
max_page_size = 10
class BookListView(ListAPIView):
queryset = BookInfo.objects.all().order_by('id')
serializer_class = BookInfoSerializer
pagination_class = StandardPageNumberPagination
# 127.0.0.1/books/?page=1&page_size=2
- LimitOffsetPagination
- 前端訪問形式:GET http://api.example.org/books/?limit=100&offset=400
- 在子類中定義的屬性
default_limit 默認(rèn)限制,默認(rèn)值與PAGE_SIZE設(shè)置一直
limit_query_param limit參數(shù)名,默認(rèn)'limit'
offset_query_param offset參數(shù)名,默認(rèn)'offset'
max_limit 最大limit限制,默認(rèn)None
from rest_framework.pagination import LimitOffsetPagination
class BookListView(ListAPIView):
queryset = BookInfo.objects.all().order_by('id')
serializer_class = BookInfoSerializer
pagination_class = LimitOffsetPagination
# 127.0.0.1:8000/books/?offset=3&limit=2
- 異常處理
- 自定義異常處理
#在類視圖方法中先手動拋出異常
#定義異常處理方法
from rest_framework.views import exception_handler as drf_exception_handler
def exception_handler(exc, context):
# 先調(diào)用REST framework默認(rèn)的異常處理方法獲得標(biāo)準(zhǔn)錯誤響應(yīng)對象
response = drf_exception_handler(exc, context)
# 在此處補充自定義的異常處理
if response is None:
view = context['view']
if isinstance(exc, DataError):
print('[%s]: %s' % (view, exc))
response = Response({'detail': '服務(wù)器內(nèi)部錯誤'},
status=status.HTTP_507_INSUFFICIENT_STORAGE)
return response
#在配置文件中聲明
REST_FRAMEWORK = {
'EXCEPTION_HANDLER': 'book.utils.exception_handler'
}
- 自動生成接口文檔
接口文檔以網(wǎng)頁的方式呈現(xiàn),自動接口文檔能生成的是繼承自APIView及其子類的視圖
-
安裝依賴
pip install coreapi
-
設(shè)置接口文檔訪問路徑
- 在總路由中添加接口文檔路徑
- 文檔路由對應(yīng)的視圖配置為rest_framework.documentation.include_docs_urls
from rest_framework.documentation import include_docs_urls
urlpatterns = [
...
url(r'^docs/', include_docs_urls(title='My API title'))
]
-
文檔描述說明的定義位置
-
單一方法的視圖,可直接使用類視圖的文檔字符串
class BookListView(generics.ListAPIView):
"""
返回所有圖書信息.
"""
-
包含多個方法的視圖,在類視圖的文檔字符串中,分開方法定義
class BookListCreateView(generics.ListCreateAPIView):
"""
get:
返回所有圖書信息.
post:
新建圖書.
"""
-
對于視圖集ViewSet,仍在類視圖的文檔字符串中分開定義,但是應(yīng)使用action名稱區(qū)分
class BookInfoViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, GenericViewSet):
"""
list:
返回圖書列表數(shù)據(jù)
retrieve:
返回圖書詳情數(shù)據(jù)
latest:
返回最新的圖書數(shù)據(jù)
read:
修改圖書的閱讀量
"""
-
訪問接口文檔網(wǎng)頁
- 瀏覽器訪問 127.0.0.1:8000/docs/,即可看到自動生成的接口文檔
- 視圖集ViewSet中的retrieve名稱,在接口文檔網(wǎng)站中叫做read
- 參數(shù)的Description需要在模型類或序列化器類的字段中以help_text選項定義
- 安裝django-filter
pip insall django-filter
- 將django-filter在settings.py中注冊應(yīng)用
- 在settings.py中的REST_FRAMEWORK,定義'DEFAULT_FILTER_BACKENDS'
- 在視圖中添加filter_fields屬性,指定可以過濾的字段
- 在瀏覽器進(jìn)行訪問時,?字段=查詢內(nèi)容
- 在試圖類中設(shè)置filter_backends,使用rest_framework.filters.OrderingFilter過濾器,REST framework會在請求的查詢字符串參數(shù)中檢查是否包含了ordering參數(shù),如果包含了ordering參數(shù),則按照ordering參數(shù)指明的排序字段對數(shù)據(jù)集進(jìn)行排序。
- 前端可以傳遞的ordering參數(shù)的可選字段值需要在ordering_fields中指明。
- 不用在settings.py中做任何配置
- 瀏覽器訪問時,通過?ordering=字段,從小到大,-字段,從大到小
filter_backends = [OrderingFilter]
ordering_fields = ('id', 'bread', 'bpub_date')
- 全局配置
REST_FRAMEWORK = { 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination', 'PAGE_SIZE': 100 # 每頁數(shù)目 } - 局部配置
-自定義Pagination類,為視圖添加分頁行為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- 可選分頁器
- PageNumberPagination
- 前端訪問:GET http://api.example.org/books/?page=4
- 在子類中定義的屬性
page_size 每頁數(shù)目 page_query_param 前端發(fā)送的頁數(shù)關(guān)鍵字名,默認(rèn)為"page" page_size_query_param 前端發(fā)送的每頁數(shù)目關(guān)鍵字名,默認(rèn)為None max_page_size 前端最多能設(shè)置的每頁數(shù)量 from rest_framework.pagination import PageNumberPagination class StandardPageNumberPagination(PageNumberPagination): page_size_query_param = 'page_size' max_page_size = 10 class BookListView(ListAPIView): queryset = BookInfo.objects.all().order_by('id') serializer_class = BookInfoSerializer pagination_class = StandardPageNumberPagination # 127.0.0.1/books/?page=1&page_size=2- LimitOffsetPagination
- 前端訪問形式:GET http://api.example.org/books/?limit=100&offset=400
- 在子類中定義的屬性
default_limit 默認(rèn)限制,默認(rèn)值與PAGE_SIZE設(shè)置一直 limit_query_param limit參數(shù)名,默認(rèn)'limit' offset_query_param offset參數(shù)名,默認(rèn)'offset' max_limit 最大limit限制,默認(rèn)None from rest_framework.pagination import LimitOffsetPagination class BookListView(ListAPIView): queryset = BookInfo.objects.all().order_by('id') serializer_class = BookInfoSerializer pagination_class = LimitOffsetPagination # 127.0.0.1:8000/books/?offset=3&limit=2
- 可選分頁器
- 自定義異常處理
#在類視圖方法中先手動拋出異常 #定義異常處理方法 from rest_framework.views import exception_handler as drf_exception_handler def exception_handler(exc, context): # 先調(diào)用REST framework默認(rèn)的異常處理方法獲得標(biāo)準(zhǔn)錯誤響應(yīng)對象 response = drf_exception_handler(exc, context) # 在此處補充自定義的異常處理 if response is None: view = context['view'] if isinstance(exc, DataError): print('[%s]: %s' % (view, exc)) response = Response({'detail': '服務(wù)器內(nèi)部錯誤'}, status=status.HTTP_507_INSUFFICIENT_STORAGE) return response #在配置文件中聲明 REST_FRAMEWORK = { 'EXCEPTION_HANDLER': 'book.utils.exception_handler' }
接口文檔以網(wǎng)頁的方式呈現(xiàn),自動接口文檔能生成的是繼承自APIView及其子類的視圖
-
安裝依賴
pip install coreapi -
設(shè)置接口文檔訪問路徑
- 在總路由中添加接口文檔路徑
- 文檔路由對應(yīng)的視圖配置為rest_framework.documentation.include_docs_urls
from rest_framework.documentation import include_docs_urls urlpatterns = [ ... url(r'^docs/', include_docs_urls(title='My API title')) ] -
文檔描述說明的定義位置
-
單一方法的視圖,可直接使用類視圖的文檔字符串
class BookListView(generics.ListAPIView): """ 返回所有圖書信息. """ -
包含多個方法的視圖,在類視圖的文檔字符串中,分開方法定義
class BookListCreateView(generics.ListCreateAPIView): """ get: 返回所有圖書信息. post: 新建圖書. """ -
對于視圖集ViewSet,仍在類視圖的文檔字符串中分開定義,但是應(yīng)使用action名稱區(qū)分
class BookInfoViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, GenericViewSet): """ list: 返回圖書列表數(shù)據(jù) retrieve: 返回圖書詳情數(shù)據(jù) latest: 返回最新的圖書數(shù)據(jù) read: 修改圖書的閱讀量 """
-
-
訪問接口文檔網(wǎng)頁
- 瀏覽器訪問 127.0.0.1:8000/docs/,即可看到自動生成的接口文檔
- 視圖集ViewSet中的retrieve名稱,在接口文檔網(wǎng)站中叫做read
- 參數(shù)的Description需要在模型類或序列化器類的字段中以help_text選項定義