rest框架包括一个处理viewset的抽象,允许开发人员集中精力处理api交互和建模,url构造都根据常见方式自动处理。
ViewSet类 几乎和VIew类一样,不过它提供read,update这样的操作,而不是get,put。
Refactoring to use ViewSets
现在来重构之前的view代码。首先把CourseList和CourseDetail重构为一个简单的CourseViewSet。
from rest_framework import viewsets from .models import Course from .serializer import CourseSerializer class CourseViewSet(viewsets.ModelViewSet): """ This viewset automatically provides `list`, `create`, `retrieve`, `update` and `destroy` actions. """ queryset = Course.objects.all() serializer_class = CourseSerializer #继承自ModelViewSet类,就是说已经自带了视图集的五个action #就是说向外暴露了五个操作接口
有时候只需要 提供只读信息,那么就只能list和retrieve,就需要只读接口
from rest_framework import viewsets from .models import UserProfile from .serializer import UserProfileSerializer class UserProfileViewSet(viewsets.ReadOnlyModelViewSet): """ retrieve : return a user info list: return all the user info """ queryset = UserProfile.objects.all() serializer_class = UserProfileSerializer #只向外暴露retrieve和list接口
自定义接口
ModelViewSet提供了全部接口,ReadOnlyModelViewSet提供了list和get接口,
接口肯定要把不必要的接口类型禁用,比如delete。
如果需要delete之外的全部接口,就需要重写视图类
class GenericViewSet(ViewSetMixin, generics.GenericAPIView): """ The GenericViewSet class does not provide any actions by default, but does include the base set of generic view behavior, such as the `get_object` and `get_queryset` methods. """ pass class ReadOnlyModelViewSet(mixins.RetrieveModelMixin, mixins.ListModelMixin, GenericViewSet): """ A viewset that provides default `list()` and `retrieve()` actions. """ pass class ModelViewSet(mixins.CreateModelMixin, mixins.RetrieveModelMixin, mixins.UpdateModelMixin, mixins.DestroyModelMixin, mixins.ListModelMixin, GenericViewSet): """ A viewset that provides default `create()`, `retrieve()`, `update()`, `partial_update()`, `destroy()` and `list()` actions. """ pass #阅读viewsets的源码,可知本质就是把mixins的几个子类引入进来 #不同接口引入不同的类
#先引入相关类 from rest_framework import mixins from rest_framework.viewsets import GenericViewSet class GameGroupViewSet(mixins.RetrieveModelMixin, mixins.UpdateModelMixin, mixins.ListModelMixin, GenericViewSet): """ retrieve: 返回指定信息 list: 返回列表 update: 更新信息 partial_update: 更新部分字段 """ queryset = GameGroup.objects.all() serializer_class = GameGroupSerializer #重写视图类
重写get_queryset
在视图类中,queryset属性一般就是model.objects.all(),但很多情况下是要对数据进行筛选修改的,所以就需要重新
class SvrFormalViewSet(viewsets.ReadOnlyModelViewSet): """ retrieve: 返回指定信息 list: 返回列表 """ serializer_class = SvrSerializer def get_queryset(self): q = ~Q(sid__in = [5000,5012,5020]) #去掉测试区 appids = [] _appids = list(Svrconfig.objects.filter(q).values('id')) #嵌套字典的列表 for appid in _appids: #转化appid的列表 appids.append(appid['id']) details = Svr.objects.filter(appid__in = appids) return details #得到的查询集不再all(),而是修改过的details
Binding ViewSets to URLs explicitly
viewset只是带进了一组action,比如list,create等。
在url中,把http方法绑定到相关的动作上。请求get,就路由到list,请求post action,就请求道create action。
courseList = views.CourseViewSet.as_view({ "get": "list", "post": "create" }) courseDetail = views.CourseViewSet.as_view({ "get": "retrieve", "put": "update", "delete": "destroy" }) urlpatterns = [ path('admin/', xadmin.site.urls), path('course/', courseList,name='course_list'), path('course/<int:pk>/', courseDetail ,name='course_detail'), ] urlpatterns = format_suffix_patterns(urlpatterns)
Using Routers
使用routers,需要做的是使用路由器注册适当的视图集,而其余的资源连接可以使用Router类自动处理。
可见,course资源相关的,只需要一个url,其他router会自动处理。
可选参数,base_name: 用来生成urls名字,如果viewset中没有包含queryset, base_name一定要有
from django.urls import path,include from rest_framework.routers import DefaultRouter from courses.views import CourseViewSet import xadmin router = DefaultRouter() router.register('course', CourseViewSet,base_name='course') urlpatterns = [ path('admin/', xadmin.site.urls), path('', include(router.urls)), ] #不再需要在app里创建urls文件,只需要在项目目录下将资源的视图集注册到router。