Various skills of Django rest framework — 4. Generic view

Time:2021-1-28

Generic view is the magic of Django, and restframework follows this powerful mechanism

Various skills of Django rest framework

Write on it

All the code is done in the following two versions

django==1.8.8
djangorestframework==3.2.5 

A previous blog explaining Django generic view
Django generics view and why it’s so important to see the source code

Implementation of a set of standard API

For example, there is a course API that supports adding, deleting, modifying and querying

url

    url(r'^courses/$', CoursesView.as_view(), name='course-list'),
    url(r'^course/(?P<pk>\d+)/$', CourseDetailView.as_view(), name='course-detail'),

view

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 'no authority of corresponding school', message = u 'no authority of corresponding school')
        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 'no authority of corresponding school', message = u 'no authority of corresponding school')
        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 'no authority of corresponding school', message = u 'no authority of corresponding school')
        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 'no authority of corresponding school', message = u 'no authority of corresponding school')
        return super(CourseDetailView, self).destroy(request, *args, **kwargs)

How do you know what to rewrite?

You can see that I have rewritten some methods according to the requirements, so which methods should I rewrite?
CD your virtualevn / local / lib / python2.7/site-packages/rest_ framework
Look at the following two files
generics.py
mixins.py

According to the inheritance relationship, you can first take a look at listcreateapiview. You can see that it provides two methods, get post. Of course, you can directly override these two methods. However, you can’t use many of its built-in things, so it’s not good to rewrite here. Instead, you should look at its corresponding mixin

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)

Let’s take get as an example, return in get self.list (request,args, *Kwargs), and this thing is mixins.ListModelMixin The method inside

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)

So here you know why restframework defines a queryset or implements get on the class_ Queryset method (please continue to see the code section of generic view, I will not post any more) defines a filter on the class_ Backends can implement continuous filters

Other kinds of mixins, you can see by yourself. I won’t repeat them.