4-drf-view component

Posted by chris9902 on Sun, 05 Dec 2021 14:58:43 +0100

One view

The main functions of the view provided by Django rest framework:

  • Controls the execution of the serializer (checking, saving, converting data)
  • Controls the execution of database queries

1.1 view inheritance

View methods and properties:

1.2 view

REST framework provides many common view base classes and extension classes to simplify view writing.

1.2.1 2 view base classes

1.2.1.1 APIView

rest_framework.views.APIView

APIView is the base class of all views provided by the REST framework, which inherits from the View parent class of Django.

APIView differs from View in that:

  • The Request object of the REST framework is passed into the view method, not the HttpRequeset object of Django;
  • The view method can return the Response object of the REST framework, and the view will render the Response data in a format that meets the requirements of the front end;
  • Any APIException will be captured and processed into appropriate response information;
  • Before dispatch() distribution, identity authentication, permission check and flow control will be performed on the request.

Support defined class properties

  • authentication_classes list or Yuanzu, identity authentication class
  • permissoin_classes list or ancestor, permission check class
  • throttle_classes list or Yuanzu, flow control class

In APIView, the methods of get(), post() or other request methods are still defined in the conventional class view.

give an example:

from rest_framework.views import APIView
from rest_framework.response import Response

# url(r'^students/$', views.StudentsAPIView.as_view()),
class StudentsAPIView(APIView):
  	
    def get(self, request):
        data_list = Student.objects.all()
        serializer = StudentModelSerializer(instance=data_list, many=True)
        return Response(serializer.data)

2.2.1.2 GenericAPIView [general view class]

rest_framework.generics.GenericAPIView

Inherited from APIVIew, it mainly adds methods for operating serializers and database queries to provide method support for the execution of the following Mixin extension classes. Usually, it can be used with one or more Mixin extension classes.

Provides information about the properties and methods used by the serializer

  • Properties:

    • serializer_class indicates the serializer used by the view
  • method:

    • get_serializer_class(self)

      When a serializer is called in a view class, the get_ can be judged by condition. serializer_ By returning different serializer class names in the class method, the view method can execute different serializer objects.

      Returns the serializer class. Serializer is returned by default_ Class, which can be overridden, for example:

      def get_serializer_class(self):
          if self.request.user.is_staff:
              return FullAccountSerializer
          return BasicAccountSerializer
      
    • get_serializer(self, *args, **kwargs)

      Returns the serializer object, which is mainly used for the Mixin extension class. If we want to get the serializer object in the view, we can also call this method directly.

      Note that when providing the serializer object, this method will supplement the context attribute of the serializer object with three data objects: request, format and view, which can be used when defining the serializer.

      • Request the request object for the current view
      • View the currently requested class view object
      • Format the data format expected to be returned by the current request

Provides properties and methods for database queries

  • Properties:

    • queryset indicates the data query set used
  • method:

    • get_queryset(self)

      The query set used by the return view is mainly used for the Mixin extension class. It is the basis for obtaining data from list view and detail view. The queryset property is returned by default and can be overridden, for example:

      def get_queryset(self):
          user = self.request.user
          return user.accounts.all()
      
    • get_object(self)

      The model class data object required to return the detail view is mainly used for the Mixin extension class.

      A model class object that can be called to get detailed information in an attempt.

      If the model class object accessed in detail does not exist, 404 will be returned.

      This method will use the check provided by APIView by default_ object_ The permissions method checks whether the current object has permission to be accessed.

      give an example:

      # url(r'^books/(?P<pk>\d+)/$', views.BookDetailView.as_view()),
      class BookDetailView(GenericAPIView):
          queryset = BookInfo.objects.all()
          serializer_class = BookInfoSerializer
      
          def get(self, request, pk):
              book = self.get_object() # get_ The object () method finds the data object in the queryset according to the pk parameter
              serializer = self.get_serializer(book)
              return Response(serializer.data)
      

Other properties that can be set

  • pagination_class indicates the paging control class
  • filter_backends indicates the filter control backend

In order to facilitate learning the generic view class above, we create a new sub application.

python manage.py startapp gen

code:

from rest_framework.generics import GenericAPIView

from students.models import Student
from .serializers import StudentModelSerializer, StudentModel2Serializer
from rest_framework.response import Response

class StudentsGenericAPIView(GenericAPIView):
    # Data to be operated in this view class [required]
    queryset = Student.objects.all()
    # Default serializer to be called in this view class [Xuantian]
    serializer_class = StudentModelSerializer

    def get(self, request):
        """Get all student information"""
        serializer = self.get_serializer(instance=self.get_queryset(), many=True)

        return Response(serializer.data)

    def post(self,request):

        data = request.data

        serializer = self.get_serializer(data=data)

        serializer.is_valid(raise_exception=True)

        instance = serializer.save()

        serializer = self.get_serializer(instance=instance)

        return Response(serializer.data)


class StudentGenericAPIView(GenericAPIView):
    queryset = Student.objects.all()

    serializer_class = StudentModelSerializer

    def get_serializer_class(self):
        """Override the method to get the serializer class"""
        if self.request.method == "GET":
            return StudentModel2Serializer
        else:
            return StudentModelSerializer

    # When using the GenericAPIView view to obtain or manipulate a single data, the parameter representing the primary key in the view method is preferably pk
    def get(self,request,pk):
        """Get a piece of data"""
        serializer = self.get_serializer(instance=self.get_object())

        return Response(serializer.data)

    def put(self,request,pk):

        data = request.data

        serializer = self.get_serializer(instance=self.get_object(),data=data)

        serializer.is_valid(raise_exception=True)

        serializer.save()

        serializer = self.get_serializer(instance=self.get_object())

        return Response(serializer.data)

Serializer class:

from rest_framework import serializers

from students.models import Student

class StudentModelSerializer(serializers.ModelSerializer):
    class Meta:
        model= Student
        fields = "__all__"


class StudentModel2Serializer(serializers.ModelSerializer):
    class Meta:
        model= Student
        fields = ("name","class_null")

1.2.2 5 view extension classes

effect:

It provides the implementation of the processing flow of several back-end views (deleted, modified and queried data resources). If the views to be written belong to these five kinds, the views can reuse the code by inheriting the corresponding extension classes to reduce the amount of code they write.

These five extension classes need to be matched with the GenericAPIView parent class, because the implementation of the five extension classes needs to call the serializer and database query methods provided by GenericAPIView.

1)ListModelMixin

The list view extension class provides list(request, *args, **kwargs) methods to quickly implement the list view and return 200 status codes.

The list method of Mixin will filter and page the data.

Source code:

class ListModelMixin(object):
    """
    List a queryset.
    """
    def list(self, request, *args, **kwargs):
        # filter
        queryset = self.filter_queryset(self.get_queryset())
        # paging
        page = self.paginate_queryset(queryset)
        if page is not None:
            serializer = self.get_serializer(page, many=True)
            return self.get_paginated_response(serializer.data)
        # serialize
        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)

give an example:

from rest_framework.mixins import ListModelMixin

class BookListView(ListModelMixin, GenericAPIView):
    queryset = BookInfo.objects.all()
    serializer_class = BookInfoSerializer

    def get(self, request):
        return self.list(request)

2)CreateModelMixin

Create the view extension class, provide the create(request, *args, **kwargs) method to quickly create the view of resources, and successfully return the 201 status code.

If the serializer fails to verify the data sent by the front end, a 400 error is returned.

Source code:

class CreateModelMixin(object):
    """
    Create a model instance.
    """
    def create(self, request, *args, **kwargs):
        # Get serializer
        serializer = self.get_serializer(data=request.data)
        # verification
        serializer.is_valid(raise_exception=True)
        # preservation
        self.perform_create(serializer)
        headers = self.get_success_headers(serializer.data)
        return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)

    def perform_create(self, serializer):
        serializer.save()

    def get_success_headers(self, data):
        try:
            return {'Location': str(data[api_settings.URL_FIELD_NAME])}
        except (TypeError, KeyError):
            return {}

3)RetrieveModelMixin

The detail view extension class provides the retrieve(request, *args, **kwargs) method, which can quickly return an existing data object.

If it exists, it returns 200, otherwise it returns 404.

Source code:

class RetrieveModelMixin(object):
    """
    Retrieve a model instance.
    """
    def retrieve(self, request, *args, **kwargs):
        # Get the object and check the permissions of the object
        instance = self.get_object()
        # serialize
        serializer = self.get_serializer(instance)
        return Response(serializer.data)

give an example:

class BookDetailView(RetrieveModelMixin, GenericAPIView):
    queryset = BookInfo.objects.all()
    serializer_class = BookInfoSerializer

    def get(self, request, pk):
        return self.retrieve(request)

4)UpdateModelMixin

Update the view extension class and provide the update(request, *args, **kwargs) method, which can quickly update an existing data object.

Partial is also provided_ Update (request, * args, * * kwargs) method can realize local update.

200 is returned successfully, and 400 error is returned when the serializer fails to verify the data.

Source code:

class UpdateModelMixin(object):
    """
    Update a model instance.
    """
    def update(self, request, *args, **kwargs):
        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)

        if getattr(instance, '_prefetched_objects_cache', None):
            # If 'prefetch_related' has been applied to a queryset, we need to
            # forcibly invalidate the prefetch cache on the instance.
            instance._prefetched_objects_cache = {}

        return Response(serializer.data)

    def perform_update(self, serializer):
        serializer.save()

    def partial_update(self, request, *args, **kwargs):
        kwargs['partial'] = True
        return self.update(request, *args, **kwargs)

5)DestroyModelMixin

Delete the view extension class and provide the destroy(request, *args, **kwargs) method, which can quickly delete an existing data object.

204 is returned successfully, and 404 is returned if it does not exist.

Source code:

class DestroyModelMixin(object):
    """
    Destroy a model instance.
    """
    def destroy(self, request, *args, **kwargs):
        instance = self.get_object()
        self.perform_destroy(instance)
        return Response(status=status.HTTP_204_NO_CONTENT)

    def perform_destroy(self, instance):
        instance.delete()

Use GenericAPIView and view extension class to implement api interface. Code:

"""GenericAPIView Combined with view extension class implementation api Interface"""
from rest_framework.mixins import ListModelMixin,CreateModelMixin
class Students2GenericAPIView(GenericAPIView,ListModelMixin,CreateModelMixin):
    # Data to be operated in this view class [required]
    queryset = Student.objects.all()
    # Default serializer to be called in this view class [Xuantian]
    serializer_class = StudentModelSerializer

    def get(self, request):
        """Get multiple student information"""
        return self.list(request)

    def post(self,request):
        """Add student information"""
        return self.create(request)


from rest_framework.mixins import RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin
class Student2GenericAPIView(GenericAPIView,RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin):
    queryset = Student.objects.all()

    serializer_class = StudentModelSerializer

    # When using the GenericAPIView view to obtain or manipulate a single data, the parameter representing the primary key in the view method is preferably pk
    def get(self,request,pk):
        """Get a piece of data"""
        return self.retrieve(request,pk)

    def put(self,request,pk):
        """Update a piece of data"""
        return self.update(request,pk)

    def delete(self,request,pk):
        """Delete a piece of data"""
        return self.destroy(request,pk)

1.2.3 view subclass of genericapiview

1)CreateAPIView

Provide post method

Inherited from: GenericAPIView, CreateModelMixin

2)ListAPIView

Provide get method

Inherited from: GenericAPIView, ListModelMixin

3)RetrieveAPIView

Provide get method

Inherited from: GenericAPIView, RetrieveModelMixin

4)DestoryAPIView

Provide delete method

Inherited from: GenericAPIView, DestoryModelMixin

5)UpdateAPIView

Provide put and patch methods

Inherited from: GenericAPIView, UpdateModelMixin

6)RetrieveUpdateAPIView

Provide get, put and patch methods

Inherited from: GenericAPIView, RetrieveModelMixin, UpdateModelMixin

7)RetrieveUpdateDestoryAPIView

Provide get, put, patch and delete methods

Inherited from: GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestoryModelMixin

1.3 view set

Using the view set ViewSet, you can put a series of logically related actions into one class:

  • list() provides a set of data
  • retrieve() provides a single piece of data
  • create() creates data
  • update() saves the data
  • Destroy() delete data

The ViewSet view set class no longer implements methods such as get() and post(), but implements action s such as list(), create().

The view set is only used in_ When using the view () method, the action action is mapped to the specific request method. For example:

class BookInfoViewSet(viewsets.ViewSet):

    def list(self, request):
        books = BookInfo.objects.all()
        serializer = BookInfoSerializer(books, many=True)
        return Response(serializer.data)

    def retrieve(self, request, pk=None):
        try:
            books = BookInfo.objects.get(id=pk)
        except BookInfo.DoesNotExist:
            return Response(status=status.HTTP_404_NOT_FOUND)
        serializer = BookInfoSerializer(books)
        return Response(serializer.data)

When setting the route, we can do the following

urlpatterns = [
    url(r'^books/$', BookInfoViewSet.as_view({'get':'list'}),
    url(r'^books/(?P<pk>\d+)/$', BookInfoViewSet.as_view({'get': 'retrieve'})
]

1.3.1 common view set parent class

1) ViewSet

It inherits from APIView and ViewSetMixin, and its function is basically similar to APIView. It provides identity authentication, permission verification, traffic management, etc.

ViewSet is mainly implemented by inheriting ViewSetMixin when calling as_ The mapping processing of the dictionary (such as {'get': 'list'}) is passed in during view().

In the ViewSet, there is no action method provided. We need to implement the action method ourselves.

2)GenericViewSet

It is usually inconvenient to use ViewSet, because the list, retrieve, create, update, destroy and other methods need to be written by ourselves, and these methods have the same name as the methods provided by the Mixin extension class mentioned above, so we can reuse these methods by inheriting the Mixin extension class without writing by ourselves. However, the Mixin extension class depends on GenericAPIView, so it also needs to inherit GenericAPIView.

GenericViewSet helps us to complete such inheritance. It inherits from GenericAPIView and ViewSetMixin, and calls as_view() is used to transfer in the dictionary (such as {'get':'list '}). At the same time, it also provides the basic methods provided by GenericAPIView, which can be used directly with the Mixin extension class.

give an example:

from rest_framework.viewsets import GenericViewSet
from rest_framework.mixins import ListModelMixin,CreateModelMixin,RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin
class Student4ViewSet(GenericViewSet,ListModelMixin,CreateModelMixin,RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin):
    queryset = Student.objects.all()
    serializer_class = StudentModelSerializer

Definition of url

urlpatterns = [
    path("students7/", views.Student4ViewSet.as_view({"get": "list", "post": "create"})),
    re_path("students7/(?P<pk>\d+)/", views.Student4ViewSet.as_view({"get": "retrieve","put":"update","delete":"destroy"})),

]

3)ModelViewSet

It inherits from GenericViewSet and includes ListModelMixin, RetrieveModelMixin, CreateModelMixin, UpdateModelMixin and DestoryModelMixin.

4)ReadOnlyModelViewSet

It inherits from GenericViewSet and includes ListModelMixin and RetrieveModelMixin.

1.3.2 define additional action actions in the view set

In the view set, in addition to the above default method actions, you can also add custom actions.

give an example:

from rest_framework.viewsets import ModelViewSet,ReadOnlyModelViewSet
class StudentModelViewSet(ModelViewSet):
    queryset = Student.objects.all()
    serializer_class = StudentModelSerializer

    def login(self,request):
        """Student login function"""
        return Response({"message":"Login succeeded"})

Definition of url

urlpatterns = [
    path("students8/", views.StudentModelViewSet.as_view({"get": "list", "post": "create"})),
    re_path("students8/(?P<pk>\d+)/",
            views.StudentModelViewSet.as_view({"get": "retrieve", "put": "update", "delete": "destroy"})),

    path("stu/login/",views.StudentModelViewSet.as_view({"get":"login"}))

]

1.3.3 action attribute

In the view set, we can use the action object attribute to get which action is when the current view set is requested.

For example:

from rest_framework.viewsets import ModelViewSet
from students.models import Student
from .serializers import StudentModelSerializer
from rest_framework.response import Response
class StudentModelViewSet(ModelViewSet):
    queryset = Student.objects.all()
    serializer_class = StudentModelSerializer

    def get_new_5(self,request):
        """Get the information of 5 recently added students"""
        # Operation database
        print(self.action) # Get the view method name of this request
        
        
Access to the current method by routing.You can see this action Is the requested method name

1.4 summary

#Two base classes
APIView
GenericAPIView: For database operations, queryset and serializer_class


#5 view extension classes (rest_framework.mixins)
CreateModelMixin: create Method to create a
DestroyModelMixin: destory Method to delete a
ListModelMixin: list Method to get all
RetrieveModelMixin: retrieve Get one
UpdateModelMixin: update Modify one

#9 subclass view (rest_framework. Genetics)
CreateAPIView:inherit CreateModelMixin,GenericAPIView,have post Method, add data
DestroyAPIView: inherit DestroyModelMixin,GenericAPIView,have delete Method to delete data
ListAPIView: inherit ListModelMixin,GenericAPIView,have get Method to get all
UpdateAPIView: inherit UpdateModelMixin,GenericAPIView,have put and patch Method to modify data
RetrieveAPIView: inherit RetrieveModelMixin,GenericAPIView,have get Method to get a


ListCreateAPIView: inherit ListModelMixin,CreateModelMixin,GenericAPIView,have get Get all, post Method addition
RetrieveDestroyAPIView: inherit RetrieveModelMixin,DestroyModelMixin,GenericAPIView,have get Method to get one, delete Method delete
RetrieveUpdateAPIView: inherit RetrieveModelMixin,UpdateModelMixin,GenericAPIView,have get Get one, put,patch modify
RetrieveUpdateDestroyAPIView: inherit RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin,GenericAPIView,have get Get one, put,patch Modification, delete delete

#View set
ViewSetMixin: Rewritten as_view 
ViewSet:      inherit ViewSetMixin and APIView

GenericViewSet: inherit ViewSetMixin, generics.GenericAPIView
ModelViewSet: inherit mixins.CreateModelMixin,mixins.RetrieveModelMixin,mixins.UpdateModelMixin,mixins.DestroyModelMixin,mixins.ListModelMixin,GenericViewSet
ReadOnlyModelViewSet: inherit mixins.RetrieveModelMixin,mixins.ListModelMixin,GenericViewSet