DRF(Django REST Framework) usage document
Function: simplify code writing and improve development speed.
The inheritance relationship is as follows: . serialize serializer -> ModelSerializer . view APIView -> GenericAPIView -> Mixin Extension class( ListModelMixin,RetrieveModelMixin,CreateModelMixin,UpdateModelMixin,DestroyModelMixin) -> Some extension classes inherit from the above . View set ViewSet GenericViewSet -> ReadOnlyModelViewSet -> ModelViewSet
install and configure
Environmental dependence
python(2.7,3.4,3.5,3.6,3.7),django(1.11,2.0,2.1)
install
pip install djangorestframework
Configuration (Registration)
vi settings.py INSTALLED_APPS = [ 'rest_framework' #DRF registration ]
A basic DRF fast creation process
- Create serializer class (serializer)
- Create a view and inherit the view set (ModelViewSet)
- Create a dynamic route (DefaultRouter)
- Display and view on the web
serialization and deserialization
. serialization is to convert the model object of database query into dictionary.
. deserialization is to convert the dictionary submitted by the front end into a model.
Serializer -- serializer
from rest_framework.serializers import Serializer
Examples
class BookInfoSerializer(serializers.Serializer): id = serializer.Intergent(label='ID', read_only=True) btitle = serializers.CharField(max_length=20, label = 'book name', required = true) bpub_ date = serializers. DateField (label = 'release time', required = true) break = serializers Charfield (max_length = 20, label = 'hits', required = false) bcomment = serializers Charfield (max_length = 20, label = 'comments', required = false) # heroinfo_ set = serializers. PrimaryKeyRelatedField(many=True)
def validate_btitle(self, value): '''Additional verification logic is added to verify the fields separately''' if 'python' not in value: raise serializers.ValidationError('Books are not about django of') return value def validate(self, attrs): '''Joint verification of multiple fields attrs: All data passed in for the front end ''' #Here, you can match and verify the two passwords, or modify the data passed in from the front end # attrs['hello'] = 'world' return attrs def create(self, validated_data): '''Calling serializer save Method was not given instance If parameters are passed, data is created''' book = BookInfo.objects.create(**validated_data) return book def update(self, instance, validated_data): '''Calling serializer save Method, here instance If the parameter is passed, the data will be updated''' instance.btitle = validated_data.get('btitle') instance.bpub_date = validated_data.get('bput_date') instance.save() return instance #Here are three ways to write foreign keys # hbook = serializers.PrimaryKeyRelatedField(label='book', read_only=True) # Serialization only # hbook = serializers.PrimaryKeyRelatedField(label='book', queryset=BookInfo.objects.all()) # For serialization and deserialization, it checks whether the assignment exists in queryset # hbook = BookInfoSerializer() # Serialize all fields in the serializer of the associated model object (that is, the data of the model object) explain: serializers.PrimaryKeyRelatedField The of the associated model ID Serialization, serializers.StringRelatedField Serializes the string of the associated model BookInfoSerializer()Serialize all fields of the associated model Option parameters of the field: max_length, min_length: maximum/Minimum length allow_blank: Allow to be empty trim_whitespace: Truncate white space characters max_value,min_value: Max, min General parameters: read_only: Only for serialization, read-only write_only: Only for deserialization, write required: Whether it is required, True / False default: Default value used for deserialization allow_null: Allow incoming null,default False validators: The verifier used by this field. error_messages: A dictionary containing error numbers and error messages label: api Field name displayed on the page help_text: api Page, display the field help prompt.
Serializer -- Modelserializer
Inherited from: Serializer,and Serializer difference 1. modelserializer Fields in the serializer can be automatically generated based on the model 2. modelserializer It has helped us achieve it create and update method
Examples
from rest_framework.serializers import ModelSerializer class BookInfoSerializer(ModelSerializer): class Meta: model = BookInfo #Specifies the serialization model name fields = '__all__' #Represents all fields of the mapping model fields = ['id','btitle','bread'] #Specify display fields exclude = ['image'] #Except for the image field, everything else is displayed extra_kwargs = { 'bread': {'min_value':0,'required':True} #When the default field of the model does not meet the requirements, you can customize the option value here 'bcomment':{'min_value':0, 'write_only':True} } read_only_fields = ['id','bread'] #The specified field is serialized only
view
Request and Response
request
.data: Return the parsed request body data. similar django of request.POST and request.FILES. .query_params: similar django of request.GET
response
rest framework Provides a response class, and the data content of the response will be converted to a type that meets the requirements of the front end. Format: Response(data, status=None,template_name=None,headers=None,content_type=None) Parameter Description: data: Serialized data prepared for response status: Status code, default 200 template_name: Template name, headers: Dictionary for storing response header information content_type: Response data Content_type,Usually, this parameter does not need to be passed. Status code: from rest_framework import status
APIView
Inherited from: django of view,and view Differences between 1. Passed in to the view is request object 2. The view returns response object 3. APIException Exceptions are caught 4. conduct dispatch()Before distribution, the request will be subject to identity authentication, permission check and flow control. Support defined attributes: . authentication_classes List or Yuanzu, identity authentication class . permission_classes List or Yuanzu, permission check class . throttle_classes List or Yuanzu, flow control class
Examples
from rest_framework.views import APIView from app1 import models from app1.serializer import BookInfoSerializer from rest_framework.response import Response from rest_framework import status class BookInfoAPIView(APIView): def get(self, request): '''Query all''' qs = models.BookInfo.objects.all() serializer = BookInfoSerializer(instance=qs, many=True) return Response(serializer.data) def post(self, request): '''newly added''' # Get the data passed in from the front end data = request.data # Create serializer for deserialization serializer = BookInfoSerializer(data=data) # Is calling serializer_ Validate serializer.is_valid(raise_exception=True) # Call the save method of the serializer to perform the create operation serializer.save() # Response front end return Response(serializer.data, status=status.HTTP_201_CREATED) class BookDetailAPIView(APIView): def get(self, request, pk): '''Query single''' try: qs = models.BookInfo.objects.get(id=pk) except models.BookInfo.DoesNotExist: return Response(status=status.HTTP_404_NOT_FOUND) serializer = BookInfoSerializer(qs) return Response(serializer.data, status=status.HTTP_202_ACCEPTED) def put(self,request,pk): '''Modify single''' try: book = models.BookInfo.objects.get(id=pk) except models.BookInfo.DoesNotExist: return Response(status=status.HTTP_404_NOT_FOUND) serializer = BookInfoSerializer(instance=book, data=request.data) serializer.is_valid(raise_exception=True) serializer.save() return Response(serializer.data, status=status.HTTP_200_OK) def delete(self,request, pk): '''Delete single''' try: book = models.BookInfo.objects.get(id=pk) except models.BookInfo.DoesNotExist: return Response(status=status.HTTP_404_NOT_FOUND) book.delete() return Response(status=status.HTTP_204_NO_CONTENT)
GenericAPIView
Inherited from APIView, different from APIView 1 Added serializer 2 Added database query method 3 Provides method support for Mixin extension classes. 4. Add paging controller 5 Add filter control
Examples
from rest_framework.generics import GenericAPIView class BookInfoGenericAPIView(GenericAPIView): # Define query set, "data source" queryset = models.BookInfo.objects.all() # Define serializer class serializer_class = BookInfoSerializer def get(self,request): #Returns the query set used by the view qs = self.get_queryset() # Returns the serializer object for serialization serializer = self.get_serializer(qs, many=True) return Response(serializer.data) def post(self,request): # Deserialize serializer = self.get_serializer(data=request.data) #Check serializer.is_valid(raise_exception=True) #preservation serializer.save() # Return to front-end dictionary return Response(serializer.data) class BookDetailGenericAPIView(GenericAPIView): '''Detail view''' # Define query set, "data source" queryset = models.BookInfo.objects.all() # Define serializer class serializer_class = BookInfoSerializer def get(self,request, pk): #Return the model class data object required by the detail view qs = self.get_object() serializer = self.get_serializer(qs) return Response(serializer.data) def put(self, request, pk): book = self.get_object() # Deserialize and call the update method in the parent class to update the data. instance is the original data and data is the new data serializer = self.get_serializer(instance=book, data=request.data) serializer.is_valid(raise_exception=True) serializer.save() return Response(serializer.data) def delete(self, request, pk): book = self.get_object() book.delete() return Response(status=status.HTTP_204_NO_CONTENT)
Extension class Mixin
There are five: listmodelmixin, createmodelmixin, retrievemodelmixin, destroymodelmixin and updatemodelmixin. They are all used together with GenericAPIView and are brothers.
Examples
from rest_framework.mixins import ListModelMixin,CreateModelMixin,RetrieveModelMixin,DestroyModelMixin,UpdateModelMixin class BookInfoGenericAPIView(ListModelMixin, CreateModelMixin, GenericAPIView): # Define the query set, "data source", which is mainly used by Mixin queryset = models.BookInfo.objects.all() # Defines the serializer class, which is mainly used by Mixin serializer_class = BookInfoSerializer def get(self,request): # Return parent class method return self.list(request) def post(self,request): # Return parent class method return self.create(request) class BookDetailGenericAPIView(RetrieveModelMixin, UpdateModelMixin,DestroyModelMixin, GenericAPIView): '''Detail view''' # Define the query set, "data source", which is mainly used by Mixin queryset = models.BookInfo.objects.all() # Defines the serializer class, which is mainly used by Mixin serializer_class = BookInfoSerializer def get(self,request, pk): return self.retrieve(request) def put(self, request, pk): return self.update(request) def delete(self, request, pk): return self.destroy(request)
Extension class
Inheritance relationship ListAPIView: Inherited from( ListModelMixin,GenericAPIView),Check all CreateAPIView: Inherited from( CreateModelMixin,GenericAPIView),newly added RetrieveAPIView: Inherited from( RetrieveModelMixin,GenericAPIView),Check single UpdateAPIView: Inherited from( UpdateModelMixin,GenericAPIView),Update single DestroyAPIView: Inherited from( DestroyModelMixin,GenericAPIView),Delete single ListCreateAPIView: Inherited from( ListModelMixin,CreateModelMixin,GenericAPIView),Check all and add RetrieveUpdateAPIView: Inherited from( RetrieveModelMixin,UpdateModelMixin,GenericAPIView)Check list and update list RetrieveDestroyAPIView: Inherited from(RetrieveModelMixin,DestroyModelMixin,GenericAPIView)Check and delete a single RetrieveUpdateDestroyAPIView: Inherited from(RetrieveModelMixin,UpdateModelMixin, DestroyModelMixin,GenericAPIView),Query a single update a single delete a single
Examples
from rest_framework.generics import GenericAPIView, ListAPIView, CreateAPIView, ListCreateAPIView,RetrieveAPIView,UpdateAPIView,DestroyAPIView, RetrieveUpdateDestroyAPIView class BookInfoGenericAPIView(CreateModelMixin, ListAPIView): perhaps class BookInfoGenericAPIView(ListCreateAPIView): # Define query set, "data source" queryset = models.BookInfo.objects.all() # Define serializer class serializer_class = BookInfoSerializer class BookDetailGenericAPIView(RetrieveAPIView,UpdateAPIView,DestroyAPIView): perhaps class BookDetailGenericAPIView(RetrieveUpdateDestroyAPIView): '''Detail view''' # Define query set, "data source" queryset = models.BookInfo.objects.all() # Define serializer class serializer_class = BookInfoSerializer
View set
You can write all additions, deletions, changes and queries into a view function. By default, it is defined: list(): query all, retrieve(): query a single, create(): create, update(): update, destroy(): delete
ViewSet
Inherited from: APIView and ViewSetMixin
ViewSet example
1. View function from rest_framework.viewsets import ViewSet class BookViewSet(ViewSet): def list(self,request): '''Define all methods of query''' qs = models.BookInfo.objects.all() serializer = BookInfoSerializer(qs, many=True) return Response(serializer.data) def retrieve(self, request, pk): '''Define query method ''' try: qs = models.BookInfo.objects.get(id=pk) except models.BookInfo.DoesNotExist: return Response(status=status.HTTP_404_NOT_FOUND) serializer = BookInfoSerializer(qs) return Response(serializer.data) 2. route url(r'^viewset-books/$', views.BookViewSet.as_view({'get':'list'})), #Create a routing map to replace the get and post methods url(r'^viewset-books/(?P<pk>\d+)/$', views.BookViewSet.as_view({'get':'retrieve'})),
GenericViewSet
Inherited from: GenericAPIView and ViewSetMixin,
GenericViewSet example
1. view from rest_framework.mixins import ListModelMixin,CreateModelMixin,RetrieveModelMixin,DestroyModelMixin,UpdateModelMixin class BookGenericcViewSet(ListModelMixin,RetrieveModelMixin,CreateModelMixin,UpdateModelMixin,DestroyModelMixin, GenericViewSet): queryset = models.BookInfo.objects.all() serializer_class = BookInfoSerializer 2. route url(r'^genericviewset-books/$', views.BookGenericcViewSet.as_view({'get':'list','post':'create'})), url(r'^genericviewset-books/(?P<pk>\d+)/$',views.BookGenericcViewSet.as_view({'get':'retrieve','put':'update','delete':'destroy'}))
ReadOnlyModelViewSet
Inherited from: ListModelMixin,RetrieveModelMixin,GenericViewSet
ReadOnlyModelViewSet example
from rest_framework.viewsets import ReadOnlyModelViewSet from rest_framework.mixins import CreateModelMixin,DestroyModelMixin,UpdateModelMixin class BookGenericcViewSet(CreateModelMixin,UpdateModelMixin,DestroyModelMixin,ReadOnlyModelViewSet ): queryset = models.BookInfo.objects.all() serializer_class = BookInfoSerializer The route is the same as above
ModelViewSet
Inherited from: ListModelMixin,RetrieveModelMixin,CreateModelMixin,UpdateModelMixin,DestroyModelMixin,GenericViewSet
ModelViewSet example
from rest_framework.viewsets import ModelViewSet class BookModelViewSet(ModelViewSet): queryset = models.BookInfo.objects.all() serializer_class = BookInfoSerializer The route is the same as above
View set customization method to realize independent functions
The view set is defined by default: the methods in list, create, update, destroy and retrieve 5. If other independent functions are implemented, they need to be customized.
Custom standalone feature example
Tips: action Method is used for dynamic routing without action Method, you can use static routing. 1. view from rest_framework.viewsets import ModelViewSet from rest_framework.decorators import action class BookModelViewSet(ModelViewSet): queryset = models.BookInfo.objects.all() serializer_class = BookInfoSerializer #Customized methods to achieve independent functions @action(methods=['get'], detail=False) # pk does not exist and detail is False def latest(self, request): qs = models.BookInfo.objects.latest('id') #Get the last book serializer = self.get_serializer(qs) #Serialize return Response(serializer.data) @action(methods=['get'], detail=True) def read(self, request, pk): '''Modify book reading''' book = self.get_object() book.read = request.data.get('bread') book.save() serializer = self.get_serializer(book) return Response(serializer.data) 2. route There are two ways to write. The first static writing method: If this behavior is not required PK,Then it is the list view, but the list view defaults to list,create, url(r'^books/latest/$', views.BookModelViewSet.as_view({'get':'latest'})), if necessary pk,Then add the following url(r'^books/(?P<pk>\d+)/read/$', views.BookModelViewSet.as_view({'put':'read'})), The second dynamic writing method (only the view set supports dynamic writing, which is required before the method action Method (decoration): from rest_framework.routers import DefaultRouter DefaultRouter Inherited from SimpleRouter(),The only difference is when the request does not have a path SimpleRouter Will report an error, DefaultRouter Multiple root routes will be generated and no error will be reported. router = DefaultRouter() #To create a router, only add, delete, modify and check by default. For additional methods, you need to add an action decorator. router.register(r'model-books', views.BookModelViewSet) #Register routing urlpatterns += router.urls #Splice the generated routes to urlpatterns router.register(prefix, viewset, base_name)Parameter interpretation .prefix: Routing prefix for view set .viewset: View set .base_name: The prefix of the route name. If it is not specified, it will be found in the view set by default queryset Property to use lowercase as the prefix of the route alias, But if not set queryset,Must be base_name Assignment.
Authentication, permission, flow restriction, filtering, sorting, paging
View independent authentication
from rest_framework.authentication import SessionAuthentication, BasicAuthentication from rest_framwork.views import APIView class ExampleView(APIView): authentication_classes = (SessionAuthentication, BasicAuthentication)
View individual permission configuration
from rest_framework.permissions import IsAuthenticated from rest_framework.views import APIView class ExampleView(APIView): permission_classes = (IsAuthenticated,) Four levels of authority . AllowAny Allow all users . IsAuthenticated Authenticated users only . IsAdminUser Administrator users only . IsAuthenticatedOrReadOnly: Authenticated users can operate completely, otherwise they can only get read
Custom permission example
inherit rest_framework.permissions.BasePermission Parent class, overriding method . has_permission(self, request, view): Add, delete, modify and query the whole view . has_object_permission(self, request, view, obj): Add, delete, modify and query data objects in a single view. return True or False class MyPermission(BasePermission): def has_object_permission(self, request, view, obj): '''Control pair obj Object access''' return False class BookInfoView(ModelViewSet): permission_classes = [IsAuthenticated, MyPermission]
Current limiting
Limit the frequency of interface access
Current limiting example
from rest_framework.throttling import UserRateThrottle from rest_framework.views import APIView class ExampleView(APIView): throttle_classes = (UserRateThrottle) Optional current limiting classes: 1): AnonRateThrottle: Restrict all anonymous unauthenticated users to use IP Distinguish users and use DEFAULT_THROTTLE_RATES['anon']To limit the frequency 2): UserRateThrottle: Restrict authenticated users, use user id To distinguish and use DEFAULT_THROTTLE_RATES['user']To set the frequency 3): ScopedRateThrottle: Limit the user's access frequency to each view, and use ip or user id,
filter
1. Filter the list data according to the fields, which can be added by django-filter Extend to enhance support pip install django-filter 2. Registration required: INSTALLED_APPS = [ 'django_filters', #Register application ] 3. Configuration file 4. Add to view filter_fields Property to specify the filtered fields class BookListView(ListAPIView): filter_fields = ('btitle','bread','id') 5. URL visit: ip:8000/books/?btitle=Journey to the West Common parameters: ?limit=10: Returns the number of records ?offset=10: Returns the start position of the record ?page=26&per_page=100: Returns the page number of records per page ?sortby=name&order=asc: Returns which attribute to sort by and the sort order ?animal_type_id=1: Specify filter criteria
sort
Sort according to the sorting field specified by the ordering parameter passed by the front end.
Sorting example
1. Global profile settings 2. The view indicates the filter and sort fields from rest_framework.filters import OrderingFilter class BookModelViewSet(ModelViewSet): #Specify filter fields filter_fields = ['id','btitle','bread'] #Specifies that the filter backend is sorted filter_backends = [OrderingFilter] # Specify sort field ordering_fields = ['id','bread'] # 127.0.0.1:8000/books/?ordering=-id sort by ID in descending order # 127.0.0.1:8000/books/?ordering=bread #IDs are sorted by bread
paging
1. Global paging reference settings.py to configure 2. Custom paging PageNumberPagination Example: from rest_framework.pagination import PageNumberPagination class LargeResultSetPag(PageNumberPagination): '''Custom paging''' page_size = 2 #Default number of items displayed per page page_query_param = 'page' # The keyword used by the front-end query string to display the name of the page page_size_query_param = 'page_size' #The keyword used by the front-end query string controls how many keywords are displayed on each page max_page_size = 5 #The front end controls how many items are displayed on each page, with a maximum of 5 items class BookModelViewSet(ModelViewSet): pagination_class = LargeResultSetPag #127.0.0.1:8000/books/?page=1&page_size=2 #Table 1, 2 entries per page 3. Custom paging LimitOffsetPagination Example: from rest_framework.pagination import LimitOffsetPagination class LimitOffset(LimitOffsetPagination): default_limit = 2 #Default number of views max_limit = 5 #Limit the maximum number of entries viewed by the front end at a time limit_query_param = 'limit' # Indicates how many items (keywords) to view offset_query_param = 'offset' #Indicates the offset, which data to view from (keyword) class BookListView(ListAPIView): pagination_class = LimitOffset # http://127..:8000/books/offset=3&limit=2 It means that from the data in Article 3, there are two in total
abnormal
REST Framework Defined exception . APIException Parent class of all exceptions . ParseError Parsing error . AuthenticationFailed Authentication failed . NoAuthenticated Not yet certified . PermissionDenied Permission denied . NotFound not found . MethodNotAllowed The request method is not supported . NotAcceptable The data format to get is not supported . Throttled Times of exceeding current limit . ValidationError Verification failed
Custom exception example
1. stay app Create exception file under: exceptions.py from rest_framework.views import exception_handler as drf_exception_handler from django.db import DatabaseError from rest_framework.response import Response from rest_framework import status def exception_handler(exc, context): '''stay DRF The exception capture of the database is added on the basis of the exception capture''' # First call the default exception handling method of REST framework to obtain the standard error response method response = drf_exception_handler(exc, context) #Custom exception handling is added here if response is None: # If it's not stopped view = context['view'] if isinstance(exc, DatabaseError): # Judge whether it is an exception of the database print('[%s]: %s' % (view, exc)) response = Response({'detail': 'Server internal error'},status = status.HTTP_507_INSUFFICIENT_STORAGE) return response 2. setting.py If there is no declaration, the default value is:'EXCEPTION_HANDLER': 'rest_framework.views.exception_handler' 3. Test, add the method in the view: from django.db import DatabaseError raise DatabaseError()
Automatically generate interface documents (only valid for DRF class view)
The REST framework can automatically generate interface documents and render them as web pages, which are inherited from the views of APIView and its subclasses.
Generate interface document example
1. Installation: pip install coreapi 2. Set interface document access path from rest_framework.documentation import include_docs_urls urlpatterns = { url(r'^docs/', include_docs_urls(title='My API title')) } 3. Description field view definition in interface document: class BookModelViewSet(ModelViewSet): ''' list: Return book list data retrieve: Return book details data latest: Return the latest book data read: Revise the reading volume of books ''' 4. visit:# http://127.0.0.1:8000/docs/
Summary of configuration parameters related to configuration files (settings.py)
REST_FRAMEWORK = { # Modify the response format of response 'DEFAULT_RENDERER_CLASSES':( 'rest_framework.renderer.JSONRenderer', #JSON renderer 'rest_framework.renderer.BrowsableAPIRenderer', #Tour API renderer ) # Turn on global authentication 'DEFAULT_AUTHENTICATION_CLASSES': ( 'rest_framework.authentication.BasicAuthentication', # Basic certification 'rest_framework.authentication.SessionAuthentication' # Session authentication ) # Global permission configuration 'DEFAULT_PERMISSION_CLASSES':( 'rest_framework.permissions.AllowAny', ) # Current limiting 'DEFAULT_THROTTLE_CLASSES':( #Current limiting configuration 'rest_framework.throttling.AnonRateThrottle', #Anonymous user 'rest_framework.throttling.UserRateThrottle' #log on user ), 'DEFAULT_THROTTLE_RATES':{ #Current limiting frequency 'anon':'100/day', # Anonymous user frequency. Optional parameters: second,minute,hour or day 'user':'1000/day' #Login user frequency } #Specify filter backend 'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',) #Specify filtering and sorting 'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend','rest_framework.filters.OrderingFilter'), # Global paging 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination', 'PAGE_SIZE': 100 #Number of pages # Custom exception declaration ''EXCEPTION_HANDLER': 'app2.exceptions.exception_handler' }