1, Request and Response in DRF
2, APIView
APIView is the base class of all views provided by DRF, which inherits from Django's View. The difference is:
- The incoming view method objects are different: DRF is Request and DJango is HTTPRequest
- The DRF view method can return the Response object, and the view will render the Response data in accordance with the format of the front end
- APIException exceptions are captured and processed as appropriate response information
- Before dispatch() distribution, identity authentication, permission check, flow control, etc. will be performed on the request
- API view still uses the conventional class view definition to implement the get, post and other request methods
from rest_framework import serializers from book.models import Book,Publish # class Publish(serializers.ModelSerializer): # class Meta: # model = Publish # fields = ['publish',] class BookModelSerializer(serializers.ModelSerializer): # publish = Publish() class Meta: model = Book fields = '__all__'
# views.py ''' List view: GET /books/ Provide all records POST /books/ Add a new record Detail view: GET /books/<str:pk>/ Provide a record PUT /books/<str:pk>/ Modify a record DELETE /books/<str:pk>/ Delete a record APIView + ModelSerializer ''' from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import status from book.models import Book from book.serializers import BookModelSerializer class BookListAPIView(APIView): """ List view """ def get(self,request): '''Query all''' # Check all the books books = Book.objects.all() # Serialize data serializer = BookModelSerializer(books,many=True) print(serializer.data) res = Response(serializer.data) # 1) . data passed to the response object after serialization, but not yet processed by render print(res.data) # 2).status_code the number of the status code print(res.status_code) # 3) . content response data after render processing # print(res.content) # The default status code is 200 return Response(serializer.data) def post(self,request): '''Add a new one''' # Get the request body data passed from the front end data = request.data # Create serializer for deserialization serializer = BookModelSerializer(data=data) # Is calling serializer_ Verify with the valid () method serializer.is_valid(raise_exception=True) # Call the save method of the serializer to execute the create method serializer.save() # response return Response(data=serializer.data,status=status.HTTP_201_CREATED) class BookDetailAPIView(APIView): """ Detail view """ def get(self,request,pk): # Query as pk model object book = Book.objects.filter(pk=pk).first() if not book: return Response(status=status.HTTP_404_NOT_FOUND) else: # Serialization using serializer classes serializer = BookModelSerializer(instance=book) return Response(serializer.data) def put(self,request,pk): # Model object modified to pk book = Book.objects.filter(pk=pk).first() if not book: return Response(status=status.HTTP_404_NOT_FOUND) else: data = request.data serializer = BookModelSerializer(instance=book,data=data) serializer.is_valid(raise_exception=True) serializer.save() return Response(serializer.data) def delete(self,request,pk): # Model object modified to pk book = Book.objects.filter(pk=pk).first() if not book: return Response(status=status.HTTP_404_NOT_FOUND) else: book.delete() return Response(status=status.HTTP_204_NO_CONTENT)
# urls.py from django.contrib import admin from django.urls import path from book.views import BookListAPIView,BookDetailAPIView from rest_framework.routers import DefaultRouter urlpatterns = [ path('admin/', admin.site.urls), path('books/',BookListAPIView.as_view()), path('books/<str:pk>/',BookDetailAPIView.as_view()) ]lo9 # # Specify DRF modelview route # router = DefaultRouter() # router.register(r'api/books',BookView) # urlpatterns += router.urls
When adding or modifying, if there is a foreign key, you need to put the associated part of the foreign key into it to add it.
3, GenericAPIView
Inherited from APIView, it mainly adds methods for operating serializers and database queries to support the execution of the following Mixin extension classes. It is often used with one or more Mixin extension classes. In addition to inheriting the three functions of APIView identity authentication, permission check and flow control, paging and filtering are also added.
3.1 GenericAPIView used alone
- List view: self.get_queryset()
- Detail view: self.get_object(), plus pk or other parameters
""" Later, when facing other serialization classes and data sources, you only need to replace them step1 and step2 that will do """ class BookListGenericView(GenericAPIView): """ List view """ # step1 specifies the serializer class serializer_class = BookModelSerializer # Step 2 specifies the query set, that is, to specify the data source queryset = Book.objects.all() # Step 3 defines the request method function def get(self,request): qs = self.get_queryset() serializer = self.get_serializer(qs,many=True) return Response(serializer.data) # The rest is the same as post ''' For the detail view, you only need to specify the of the query later pk that will do lookup_field = 'pk' If you need to change the query pk Modifiable lookup_field Name the field you want to query ''' class BookDetailGenericView(GenericAPIView): """ List view """ # step1 specifies the serializer class serializer_class = BookModelSerializer # Step 2 specifies the query set, that is, to specify the data source queryset = Book.objects.all() # Step 3 defines the request method function def get(self,request,pk): book = self.get_object() serializer = self.get_serializer(book) return Response(serializer.data) # The rest are the same as put delete
urlpatterns = [ path('admin/', admin.site.urls), # path('books/',BookListAPIView.as_view()), # path('books/<str:pk>/',BookDetailAPIView.as_view()), path('books/',BookListGenericView.as_view()), path('books/<str:pk>/',BookDetailGenericView.as_view()) ]
3.2 genericapiview & mixin implementation interface
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.
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.
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.
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.
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.
class BookListMixinGenericView(ListModelMixin, CreateModelMixin, GenericAPIView): # Specifies the serializer class serializer_class = BookModelSerializer # Specify data source queryset = Book.objects.all() def get(self, request): return self.list(request) def post(self, request): return self.create(request) class BookDetailMixinGenericView(RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin, GenericAPIView): # Specifies the serializer class serializer_class = BookModelSerializer # Specify data source queryset = Book.objects.all() def get(self, request, pk): return self.retrieve(request, pk) def put(self, request, pk): return self.update(request, pk) def delete(self, request, pk): return self.destroy(request, pk)
3.3 ListAPIView & CreateAPIView & ListCreateAPIView ...
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
class BookListMixinGenericView(ListModelMixin, CreateModelMixin, GenericAPIView): # Specifies the serializer class serializer_class = BookModelSerializer # Specify data source queryset = Book.objects.all() def get(self, request): return self.list(request) def post(self, request): return self.create(request) class BookListMixinGenericView(ListAPIView,CreateAPIView): # Specifies the serializer class serializer_class = BookModelSerializer # Specify data source queryset = Book.objects.all() class BookListMixinGenericView(ListCreateAPIView): # Specifies the serializer class serializer_class = BookModelSerializer # Specify data source queryset = Book.objects.all()
4, View set
View set: previously, the detail view and list view were written separately, because there are two get requests (query all and single), and the view set is to unify these interfaces, write the two views to the same view class, and customize other methods
4.1 ViewSet
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 BookViewSet(ViewSet): """ View set: previously, the detail view and list view were written separately, Because there are two get Request (query all and individual), and the view set is to unify these interfaces, The two views are written to the same view class, and other methods can be customized """ def list(self,request): # Query all books = Book.objects.all() # Query set to add many=True serializer = BookModelSerializer(books,many=True) return Response(serializer.data) def create(self,request): serializer = BookModelSerializer(data=request.data) serializer.is_valid(raise_exception=True) serializer.save() return Response(serializer.data) def retrieve(self,request,pk): # Query objects with pk book = Book.objects.filter(pk=pk).first() if not book: return Response(status=status.HTTP_404_NOT_FOUND) else: serializer = BookModelSerializer(book) return Response(serializer.data) def update(self,request,pk): # Query objects with pk book = Book.objects.filter(pk=pk).first() if not book: return Response(status=status.HTTP_404_NOT_FOUND) else: # json data from the data front end serializer = BookModelSerializer(book, data=request.data) serializer.is_valid(raise_exception=True) serializer.save() return Response(serializer.data, status=status.HTTP_200_OK) def destroy(self,request,pk): book = Book.objects.filter(pk=pk).first() if not book: return Response(status=status.HTTP_404_NOT_FOUND) else: book.delete() return Response(status.HTTP_204_NO_CONTENT)
urlpatterns = [ path('admin/', admin.site.urls), # path('books/',BookListAPIView.as_view()), # path('books/<str:pk>/',BookDetailAPIView.as_view()), # path('books/',BookListGenericView.as_view()), # path('books/<str:pk>/',BookDetailGenericView.as_view()), path('books/',BookViewSet.as_view({'get':'list','post':'create'})), path('books/<str:pk>/',BookViewSet.as_view({'get':'retrieve','put':'update','delete':'destory'})) ]
4.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.
ModelViewSet
It inherits from GenericViewSet and includes ListModelMixin, RetrieveModelMixin, CreateModelMixin, UpdateModelMixin and DestoryModelMixin
ReadOnlyModelViewSet
It inherits from GenericViewSet and includes ListModelMixin and RetrieveModelMixin
class BookViewSet(ListModelMixin,RetrieveModelMixin,GenericViewSet): # class BookViewSet(ModelViewSet): """ View set: previously, the detail view and list view were written separately, Because there are two get Request (query all and individual), and the view set is to unify these interfaces, The two views are written to the same view class, and other methods can be customized """ queryset = Book.objects.all() serializer_class = BookModelSerializer class BookViewSet(ReadOnlyModelViewSet): # class BookViewSet(ModelViewSet): """ ReadOnlyModelViewSet: books/ & books/1/ get request ModelViewSet: books/ & books/1/ get request put delete """ queryset = Book.objects.all() serializer_class = BookModelSerializer """ Additional definitions none pk """ # For the behaviors defined outside the normal addition, deletion, modification and query, a separate route should be defined for them # If pk is not required for this behavior, it is a list view, # But the list view only has list create # URL: path(r'books/latest/',BookViewSet.as_view({'get':'latest'})) """action Detailed explanation of decorator parameters methods: Response to this operation HTTP List of method names. Default only GET. detail: Required parameters. Determines whether this action applies to the instance/Detail request or collection/List request. detail=False Not a detail view; detail=TRUE Detail view url_path:Define the for this operation URL Paragraph. The default is the name of the decorated method. url_name:Define an internal for this action(' reverse ') URL name. The default is the method name, with underscores instead of dashes. """ @action(methods="get",detail=False) def latest(self,request): pass """ Additional definitions are pk """ # Yes pk is the detail view # The details view includes: get put delete # URL: path(r'books/<int:pk>/latest/',BookViewSet.as_view({'get':'read'})) @action(methods='get',detail=True) def title(self, request,pk): book = self.get_object() book.title = request.data['title'] book.save() # return Response(self.get_serializer(book).data) pass
4.3 route definition
General definition
""" Additional definitions none pk """ # For the behaviors defined outside the normal addition, deletion, modification and query, a separate route should be defined for them # If pk is not required for this behavior, it is a list view, # But the list view only has list create # URL: path(r'books/latest/',BookViewSet.as_view({'get':'latest'})) """ Additional definitions are pk """ # Yes pk is the detail view # The details view includes: get put delete # URL: path(r'books/<int:pk>/latest/',BookViewSet.as_view({'get':'read'}))
Defaultrouter & simplerouter definition
# # Specify DRF modelview route # This method is only suitable for use in the view set, and can only generate the five basic routes of standard addition, deletion, modification and query # If you want the custom behavior to generate routes, you need to use the action behavior in the custom behavior and specify the corresponding request method """action Detailed explanation of decorator parameters methods: Response to this operation HTTP List of method names. Default only GET. detail: Required parameters. Determines whether this action applies to the instance/Detail request or collection/List request. detail=False Not a detail view; detail=TRUE Detail view url_path:Define the for this operation URL Paragraph. The default is the name of the decorated method. url_name:Define an internal for this action(' reverse ') URL name. The default is the method name, with underscores instead of dashes. """ # The only difference between DefaultRouter and SimpleRouter is that DefaultRouter will generate a root route by default and SimpleRouter will not # router = DefaultRouter() # router.register(r'api/books',BookViewSet) # urlpatterns += router.urls