首页 > 其他 > 详细

DRF(七)

时间:2019-09-10 21:56:17      阅读:125      评论:0      收藏:0      [点我收藏+]

一.准备工作:

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)

 

DRF(七)

原文:https://www.cnblogs.com/sima-3/p/11502870.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!