zoukankan      html  css  js  c++  java
  • DRF(七)

    一.准备工作:

    1.主路由:

    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^api/', include('api.urls')),
    ]

    2.api路由:

    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

    5.视图类:

    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': '删除成功'
                })
            except:
                return Response({
                    'status': 1,
                    'msg': '删除失败'
                })
       def list(self, request, *args, **kwargs):
    response = super().list(request, *args, **kwargs)
    return Response({
    'status': 0,
    'msg': 'ok',
    'results': response.data
    })
     

    二.路由组件 (写前面信息'cars'即可,有名分组自动补全pk):

    from . import views
    from rest_framework.routers import SimpleRouter
    # 初始化路由对象
    router = SimpleRouter()
    
    # 注册各种接口路由
    router.register('cars', views.CarModelViewSet, base_name='car')
    # router.register('brands', views.BrandModelViewSet, base_name='brand')
    
    urlpatterns = [   ]
    urlpatterns.extend(router.urls)

    三.搜索组件

    主要是利用mixins.ListModelMixin类找到queryset,进而进行搜索,过滤,排序等操作

    在filters.py文件中有SearchFilter和OrderingFilter两个类:

    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.')

    需要两个参数:

        def filter_queryset(self, request, queryset, view):
            search_fields = self.get_search_fields(view, request)
            search_terms = self.get_search_terms(request)

    视图类中自定义写法:

        from rest_framework.filters import SearchFilter, OrderingFilter
        # 搜索组件
        # 接口:/cars/?search=秦  ||  /cars/?search=1  在name和price两个字段中模糊搜索
        filter_backends = [SearchFilter]
        # 默认模糊查询,等价$,以什么开头^,精确匹配=,@??
        search_fields = ['name', 'price']

    四.排序组件(支持倒序)

        filter_backends = [SearchFilter, OrderingFilter]
        ordering_fields = ['pk', 'price']
       # 接口: api/cars/?search=1&ordering=-pk

    五.筛选组件

    安装:

    pip install django-filter

    配置:

    INSTALLED_APPS = [
        ...
        'django_filters',  # 需要注册应用,
    ]
    
    全局(也可以设置局部): REST_FRAMEWORK
    = { ... 'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',) }

    视图类中:

        
       from .filtersets import CarFilterSet

    # 筛选(分类、区间) filter_backends = [SearchFilter, OrderingFilter, DjangoFilterBackend] # 分类:一般都是可以分组的字段 # filter_fields = ['brand'] # 区间,也可以包含分类,提倡 筛选 就采用该方式 filter_class = CarFilterSet

    区间类:

    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还是实现分类
            # min_price,max_price可以定义区间
            fields = ['brand', 'min_price', 'max_price']

    六.分页组件

    视图分页:

     # 分页
        # 普通分页(最常用)
        # pagination_class = pagination.CarPageNumberPagination
        # 偏移分页
        # pagination_class = pagination.CarLimitOffsetPagination
        # 加密分页
        pagination_class = pagination.CarCursorPagination

    自定义pagination.py:

    from rest_framework.pagination import PageNumberPagination
    # 普通分页
    class CarPageNumberPagination(PageNumberPagination):
        # 默认一页的条数
        page_size = 3
        # 用户可以自定义选择一页的条数,但最多显示5条
        page_size_query_param = 'page_size'
        max_page_size = 5
        # 默认条数访问 /cars/?page=页面号
        #       eg:/cars/?page=1
        # 自定义条数访问 /cars/?page=页面号&page_size=一页的条数
        #       eg:/cars/?page=1&page_size=5
    
    
    from rest_framework.pagination import LimitOffsetPagination
    # 偏移分页
    class CarLimitOffsetPagination(LimitOffsetPagination):
        # 默认一页的条数
        default_limit = 3
        # limit控制一页显示的条数,offset控制偏移的条数(从头开始计数)
        limit_query_param = 'limit'
        offset_query_param = 'offset'
        # 限制limit可以设置的最大显示条数
        max_limit = 5
        # 接口 /cars/?limit=一页的条数&offset=偏移的条数
        #       eg:/cars/?limit=5&offset=2  # 显示3~7条
    
    
    
    from rest_framework.pagination import CursorPagination
    # 加密分页
    class CarCursorPagination(CursorPagination):
        # 默认一页的条数
        page_size = 3
        # 用户可以自定义选择一页的条数,但最多显示5条
        page_size_query_param = 'page_size'
        max_page_size = 5
        # 默认排序规则
        ordering = 'pk'
        # 采用默认排序访问 /cars/?cursor=加密串
        #       eg:/cars/?cursor=cD0z
        # 结合视图类实现OrderingFilter自定义排序规则
        #  /cars/?cursor=加密串&ordering=排序字段
        #       eg:/cars/?cursor=cD0z&ordering=-price

    七.异常处理

    配置:

    # drf配置
    REST_FRAMEWORK = {
        'EXCEPTION_HANDLER': 'api.exception.exception_handler'
    }

    自定义exception:

    # rest_framework.views 下的 exception_handler 处理了所有 drf可控范围内的异常
    from rest_framework.views import exception_handler as drf_exception_handler
    # drf的异常还是交给 drf_exception_handler,我们只需要处理 drf未处理的异常
    
    from rest_framework.response import Response
    
    # 自定义异常句柄的原因:要通过 logging 记录异常日志
    def exception_handler(exc, context):
        response = drf_exception_handler(exc, context)
    
        if response is None:
            # drf处理不了的异常
            return Response({
                'exception': '服务器异常',
            }, status=500)
    
        response.exception = True
        return response

    八.接口文档(yapi)

  • 相关阅读:
    利用SqlBulkCopy快速大批量导入数据
    未能完成操作,无效的FormATETC结构
    JS编码和Asp.net编码
    Sql分页两种常用算法
    Subsonic.exe 生成数据访问层代码,报“从索引 0 处开始,初始化字符串的格式不符合规范”错误解决办法
    Asp.Net,代码实现页面输出缓存
    JS中all Collection 的几个方法
    注册、反注册dll,regsvr32命令详解
    ASP.NET页面传值汇总(Session/Server.Transfer/Query String/Cookie/Application)
    表格导出EXCEL
  • 原文地址:https://www.cnblogs.com/sima-3/p/11502870.html
Copyright © 2011-2022 走看看