DRF secondary view GenericAPIView

Posted by elfynmcb on Sun, 19 Dec 2021 12:47:32 +0100

GenericAPIView

GenericAPIView inherits from APIView and adds general support methods that may be used for list view and detail view. Usually, it can be used with one or more Mixin extension classes.

attribute

Basic settings:

The following properties control the behavior of the base view.

List view: get multiple pieces of data (or all data), for example: get all books

Detail view: obtain single data, such as the price, author, publishing house, etc. of journey to the West.

List view and detail view are common

  • queryset applies to the query set of objects returned from this view. Typically, you must set this property or override it_ queryset() method. If you want to override the view method, be sure to call get_queryset() instead of accessing this property directly.
  • serializer_class should be used to validate and deserialize the input and serialize the output. Typically, you must set this property or override it_ serializer_class() method.

Details view usage

  • lookup_field should be used to perform object lookup for a single model instance. The default is' pk '
  • lookup_ url_ The URL keyword parameter that kwarg should use for object lookup. The URL conf should contain a keyword parameter corresponding to this value. If not set, lookup is used by default_ field.

paging

The following properties are used to control paging when used with list views.

  • pagination_class is the paging class that should be used when paging list results. The default is and DEFAULT_PAGINATION_CLASS sets the same value, that is, 'rest'_ framework. pagination. PageNumberPagination’. Setting pagination_class=None will disable paging for this view.

filter

  • filter_backends a list of filter backend classes that are applied to filter the query set. Default and DEFAULT_FILTER_BACKENDS settings are the same.

method

List view and detail view are common

get_queryset(self) returns the query set used by the view. It is the basis for obtaining data from list view and detail view. The queryset property is returned by default and can be rewritten, for example:

def get_queryset(self):
    return BookInfo.objects.all()

get_serializer_class(self) returns the serializer class. Serializer is returned by default_ Class, which can be overridden, for example:

def get_serializer_class(self):
    return BookInfoModelSerializer

get_serializer(self, _args, *_kwargs) returns the serializer object, which is used by other views or extension classes. If we want to get the serializer object in the view, we can call this method directly.

Details view usage

get_object(self) returns the model class data object required by the detail view. Lookup is used by default_ Field parameter to filter queryset. The model class object that can call this method to obtain detailed information in the view.

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

Experience: GenericAPIView looks very beautiful and can be combined with various mixin s, but it is not very useful in fact. This is because the development speed is improved at most, but if the product modifies the requirements, the corresponding serializer must be changed. Then, some interfaces need A serializer for data verification, and some need B serializer. It is very inconvenient to change GenericAPIView at this time.

Suggestion: use FVB mode for development, which is easy to modify, or there is only one method in each CVB, but it is not as good as using FVB directly.

Here are some examples. Some of these examples use pagers. This does not affect our understanding. If you don't know the of the DRF pager, you can see it here

Lists and new views

In the list view, multiple data are returned according to the page size at a time. As shown in the figure below, when we use Baidu search, Baidu will show us the data in the form of pagination.

Our list view code is as follows:

class PageNum(PageNumberPagination):
    """Pager class"""
    page_size = 10  # By default, the number of entries returned per page
    page_query_param = 'pagenum'     #Set the key of page in the url. The default is page
    page_size_query_param = 'pagesize'  # Set page in url_ The size key, which defaults to page_size
    max_page_size = 50  # Maximum number of entries returned per page


class BookListView(GenericAPIView):
    """List view"""
    queryset = BookInfo.objects.all().order_by('id')
    serializer_class = BookInfoSerializer
    pagination_class = PageNum


    def get(self, request):
        """GET Request get list"""
        data = self.get_queryset()      # Get query result set
        page = self.paginate_queryset(data)    #Pagination of query result set
        serializer = self.get_serializer(page, many=True)   # serialize
        return Response(serializer.data)    # Return value


    def post(self, request):
        """post Request new"""
        data = request.data
        serializer = self.get_serializer(data=data)
        if serializer.is_valid(raise_exception=True):
            serializer.save()
            return Response(serializer.data, status=201)
        else:
            # Return error message
            return Response({'msg': 'Save failed'}, status=400)

Use the GET method to request. The effect is as follows:

After adding successfully, the returned response is as follows:

The reason why the list method and the new method are placed in one class is that "the URLs used by the two methods are the same, while the URLs used to query a piece of data details, modify an existing piece of data, and delete a piece of data are the same."

Delete modify query view

The view will include three functions: deleting a piece of data, modifying a piece of data and obtaining the details of a piece of data. The corresponding HTTP request methods are DELETE, PUT and GET respectively. They use the same URL.

class BookView(GenericAPIView):
    """Delete modify query view"""
    queryset = BookInfo.objects.all()
    serializer_class = BookInfoSerializer
    lookup_field = 'pk'
    lookup_url_kwarg = 'pk'

    def get(self, request, pk):
        """according to id Query book details"""
        obj = self.get_object()
        serializers = self.get_serializer(obj)

        return Response(serializers.data)

    def delete(self, request, pk):
        """according to id Delete books"""
        obj = self.get_object()
        obj.delete()

        return Response(status=204)

    def put(self, request, pk):
        """according to id Modify the information of a Book"""
        obj = self.get_object()
        data = request.data
        serializers = self.get_serializer(obj, data)
        if serializers.is_valid(raise_exception=True):
            serializers.save()
            # PUT update. If data is returned, the recommended status code is 200; If no data is returned, the status code can be 204 or 205 according to the situation
            return Response(serializers.data, status=200)   
        else:
            return Response(status=400)

Our URL design is as follows:

path('book', BookListView.as_view()),
path('book/<int:pk>', BookView.as_view()),

use http://127.0.0.1:8848/book/3 Make a request, and the returned response is as follows:

This basically reflects the design idea of RESTFul. Only nouns are involved in the URL, the interface is unified, and the HTTP request method is used to distinguish actions. Different HTTP methods represent different operations on resources.