generic view是django神奇的地方,而restframework遵循了這個powerful的機制python
Django REST framework的各類技巧【目錄索引】django
全部的代碼都是在下面的兩個版原本作的segmentfault
django==1.8.8 djangorestframework==3.2.5
一個以前的blog,解釋django generic view Django generics view 以及看源碼爲何這麼重要api
例若有一個課程類的api,支持增刪改查python2.7
urlpost
url(r'^courses/$', CoursesView.as_view(), name='course-list'), url(r'^course/(?P<pk>\d+)/$', CourseDetailView.as_view(), name='course-detail'),
viewui
class CoursesView(ListCreateAPIView): filter_backends = (SchoolPermissionFilterBackend, filters.DjangoFilterBackend, filters.SearchFilter) permission_classes = (IsAuthenticated, ModulePermission) queryset = Course.objects.filter(is_active=True).order_by('-id') filter_fields = ('term',) search_fields = ('name', 'teacher', 'school__name') module_perms = ['course.course'] def get_serializer_class(self): if self.request.method in SAFE_METHODS: return CourseFullMessageSerializer else: return CourseSerializer def get_queryset(self): return Course.objects.select_related('school', ).filter( is_active=True, school__is_active=True, term__is_active=True).order_by('-id') @POST('school', validators='required') def create(self, request, school, *args, **kwargs): if not SchoolPermissionFilterBackend().has_school_permission(request.user, school): raise Error(errors.PermissionDenied, err_message=u'沒有對應學校的權限', message=u'沒有對應學校的權限') serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True) self.perform_create(serializer) headers = self.get_success_headers(serializer.data) return Response(CourseFullMessageSerializer(serializer.instance).data, status=status.HTTP_201_CREATED, headers=headers class CourseDetailView(UnActiveModelMixin, DeleteForeignObjectRelModelMixin, RetrieveUpdateDestroyAPIView): filter_backends = [SchoolPermissionFilterBackend,] serializer_class = CourseSerializer permission_classes = (IsAuthenticated, ModulePermission) queryset = Course.objects.filter(is_active=True).order_by('-id') module_perms = ['course.course'] def get_serializer_class(self): if self.request.method in SAFE_METHODS: return CourseFullMessageSerializer else: return CourseSerializer def retrieve(self, request, *args, **kwargs): instance = self.get_object() school = instance.school if not SchoolPermissionFilterBackend().has_school_permission(request.user, school): raise Error(errors.PermissionDenied, err_message=u'沒有對應學校的權限', message=u'沒有對應學校的權限') serializer = self.get_serializer(instance) return Response(serializer.data) @POST('school', validators='required') def update(self, request, school, *args, **kwargs): if not SchoolPermissionFilterBackend().has_school_permission(request.user, school): raise Error(errors.PermissionDenied, err_message=u'沒有對應學校的權限', message=u'沒有對應學校的權限') partial = kwargs.pop('partial', False) instance = self.get_object() serializer = self.get_serializer(instance, data=request.data, partial=partial) serializer.is_valid(raise_exception=True) self.perform_update(serializer) return Response(CourseFullMessageSerializer(serializer.instance).data) def destroy(self, request, *args, **kwargs): instance = self.get_object() school = instance.school if not SchoolPermissionFilterBackend().has_school_permission(request.user, school): raise Error(errors.PermissionDenied, err_message=u'沒有對應學校的權限', message=u'沒有對應學校的權限') return super(CourseDetailView, self).destroy(request, *args, **kwargs)
能夠看到我根據需求重寫了一些方法,那麼到底應該重寫那些方法呢? cd 你的virtualevn/local/lib/python2.7/site-packages/rest_framework 請看下面兩個文件 generics.py mixins.pyurl
根據繼承關係能夠先看下ListCreateAPIView,能夠看到他提供了get post兩個方法,你固然能夠直接重寫這兩個方法,然而就不能用他不少內置的東東,因此重寫這裏並很差,而應該看他對應的mixin.net
class ListCreateAPIView(mixins.ListModelMixin, mixins.CreateModelMixin, GenericAPIView): """ Concrete view for listing a queryset or creating a model instance. """ def get(self, request, *args, **kwargs): return self.list(request, *args, **kwargs) def post(self, request, *args, **kwargs): return self.create(request, *args, **kwargs)
咱們已get爲例,get中return self.list(request, *args, **kwargs),而這個東東是mixins.ListModelMixin裏面的方法rest
class ListModelMixin(object): """ List a queryset. """ def list(self, request, *args, **kwargs): queryset = self.filter_queryset(self.get_queryset()) page = self.paginate_queryset(queryset) if page is not None: serializer = self.get_serializer(page, many=True) return self.get_paginated_response(serializer.data) serializer = self.get_serializer(queryset, many=True) return Response(serializer.data)
因此在這裏你就知道爲嘛restframework在class上要定義一個queryset或者實現get_queryset方法(請繼續看generic view的代碼部分,我不貼了),爲嘛class上定義一個filter_backends能夠實現繼續的filter
其餘的各類mixin各位同窗本身看代碼就知道了,觸類旁通我再也不贅述。