I. Preparation:
1. The main routes:
urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^api/', include('api.urls')), ]
2.api route:
from django.conf.urls import url
from . import views
urlpatterns = [ url(r'^cars/$', views.CarModelViewSet.as_view({ 'get': 'list', 'post': 'create' })), url(r'^cars/(?P<pk>.*)/$', views.CarModelViewSet.as_view({ 'get': 'retrieve', 'put': 'update', 'patch': 'partial_update', 'delete': 'destroy' })), ]
3.setting.py:
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'api.apps.ApiConfig', 'rest_framework', ]
4.models:
from django.db import models class BaseModel(models.Model): is_delete = models.BooleanField(default=0) create_time = models.DateTimeField(auto_now_add=True) class Meta: abstract = True class Car(BaseModel): name = models.CharField(max_length=32) price = models.DecimalField(max_digits=5, decimal_places=2) brand = models.ForeignKey('Brand', db_constraint=False, on_delete=models.DO_NOTHING, related_name='cars') @property def brand_name(self): return self.brand.name class Meta: db_table = 'old_boy_car' verbose_name = '汽车' verbose_name_plural = verbose_name def __str__(self): return self.name class Brand(BaseModel): name = models.CharField(max_length=16) class Meta: db_table = 'old_boy_brand' verbose_name = '品牌' verbose_name_plural = verbose_name def __str__(self): return self.name
The view class:
class CarModelViewSet(ModelViewSet): queryset = models.Car.objects.filter(is_delete=False) serializer_class = serializers.CarModelSerializer def destroy(self, request, *args, **kwargs): pk = kwargs.get('pk') try: car_obj = models.Car.objects.get(pk=pk, is_delete=False) car_obj.is_delete = True car_obj.save() return Response({ 'status': 0, ' MSG ' : ' successfully deleted ' }) the except : return the Response ({ ' Status ' :. 1 , ' MSG ' : ' delete failed ' })
def list(self, request, *args, **kwargs):
response = super().list(request, *args, **kwargs)
return Response({
'status': 0,
'msg': 'ok',
'results': response.data
})
II routing component (the write information is preceded by 'cars' to, known automatic completion packet pk):
from . Import views from rest_framework.routers Import SimpleRouter # initialization-routing objects Router = SimpleRouter () # registration various interfaces routing router.register ( ' cars ' , views.CarModelViewSet, base_name = ' CAR ' ) # router.register (' Brands ', views.BrandModelViewSet, base_name =' Brand ') the urlpatterns = [] urlpatterns.extend (router.urls)
III. The search component
Mainly using mixins.ListModelMixin class QuerySet found, further searching, filtering, sorting and other operations
There are two classes in SearchFilter and OrderingFilter filters.py file:
class SearchFilter(BaseFilterBackend): # The URL query parameter used for the search. search_param = api_settings.SEARCH_PARAM 默认是search template = 'rest_framework/filters/search.html' lookup_prefixes = { '^': 'istartswith', '=': 'iexact', '@': 'search', '$': 'iregex', } search_title = _('Search') search_description = _('A search term.')
It requires two parameters:
def filter_queryset(self, request, queryset, view): search_fields = self.get_search_fields(view, request) search_terms = self.get_search_terms(request)
Custom view class written:
from rest_framework.filters import SearchFilter, OrderingFilter
# Search Component # interfaces:?? / Cars / search = Qin || / cars / search = 1 fuzzy search in name and price of the two fields filter_backends = [searchfilter] # default fuzzy query, equivalent to $, beginning with what ^ exact match = @? ? = search_fields [ ' name ' , ' . price ' ]
IV. Sort component (support reverse)
filter_backends = [SearchFilter, OrderingFilter] ordering_fields = ['pk', 'price']
# 接口: api/cars/?search=1&ordering=-pk
V. screening components
installation:
pip install django-filter
Configuration:
= The INSTALLED_APPS [ ... ' django_filters ' , # need to register the application, ]
global (can also be provided locally): REST_FRAMEWORK = { ... ' DEFAULT_FILTER_BACKENDS ' : ( ' django_filters.rest_framework.DjangoFilterBackend ' ,) }
View class:
from .filtersets import CarFilterSet
# Screening (classification section) filter_backends = [searchfilter, OrderingFilter, DjangoFilterBackend] # Category: field generally can be grouped # filter_fields = [ 'Brand'] # interval, classification may also comprise, screened to promote this manner filter_class = CarFilterSet
Interval categories:
from django_filters.rest_framework import FilterSet from django_filters import filters from . import models class CarFilterSet(FilterSet): min_price = filters.NumberFilter(field_name='price', lookup_expr='gte') max_price = filters.NumberFilter(field_name='price', lookup_expr='lte') class Meta: model = models.Car # Brand to classify or # MIN_PRICE, can define the interval of max_price Fields = [ ' Brand ' , ' MIN_PRICE ' , ' of max_price ' ]
VI. Paging component
Page views:
# Page # Normal tab (most common) # pagination_class = pagination.CarPageNumberPagination # offset tab # pagination_class = pagination.CarLimitOffsetPagination # encryption tab pagination_class = pagination.CarCursorPagination
Custom pagination.py:
from rest_framework.pagination Import PageNumberPagination # ordinary paging class CarPageNumberPagination (PageNumberPagination): # default under a number PAGE_SIZE. 3 = # user may customize a number of selected, but a maximum of 5 bar page_size_query_param = ' PAGE_SIZE ' MAX_PAGE_SIZE. 5 = # the default number of access / cars / page = page number? # EG:? / cars / page = 1 # ? customize the number of access / cars / page = page number & page_size = one of the number # EG: / cars / ? Page = 5 = 1 & PAGE_SIZE from rest_framework.pagination Import LimitOffsetPagination # offset pagination class CarLimitOffsetPagination (LimitOffsetPagination): # default page number of default_limit. 3 = # number of a display control limit, offset number of offset control (counting from the beginning) limit_query_param = ' limit ' offset_query_param = ' offset ' # restrictions limit the maximum number display bar can be set max_limit =. 5 # Interface / cars / number of limit = one of & offset = offset the number? # EG:? / cars / limit =. 5 & offset = 2 # display 3 to 7 from rest_framework .pagination Import CursorPagination # encryption paging class CarCursorPagination (CursorPagination): # default page number of =. 3 PAGE_SIZE # user may customize a number of selected, but a maximum of 5 bar page_size_query_param = ' PAGE_SIZE ' MAX_PAGE_SIZE =. 5 # default collation Ordering = ' PK ' # default ordering access / cars /? cursor = encryption string # EG: / cars / Cursor = cD0z? # binding view class OrderingFilter implement custom collation # / cars / Cursor encryption string = & ordering = sort field? # EG: / cars / Cursor = cD0z & ordering = -Price?
VII. Exception Handling
Configuration:
# drf配置 REST_FRAMEWORK = { 'EXCEPTION_HANDLER': 'api.exception.exception_handler' }
Custom exception:
# Rest_framework.views exception_handler under abnormal processing all drf controllable range from rest_framework.views Import exception_handler AS drf_exception_handler # abnormal drf or to drf_exception_handler, we only have to deal drf unhandled exception from rest_framework.response Import the Response # exception handler custom reasons: to exception log records by logging DEF exception_handler (EXC, context): Response = drf_exception_handler (EXC, context) IF Response iS None: # DRF exception processing can not return the Response ({ ' exception ' : 'Server abnormal ' , }, Status = 500 ) response.exception = True return Response
VIII. Interface documentation (yapi)