首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Django REST 框架详解 05 | 视图家族 Mixins

Django REST 框架详解 05 | 视图家族 Mixins

作者头像
白墨石
发布2021-01-12 09:59:33
发布2021-01-12 09:59:33
1.4K00
代码可运行
举报
文章被收录于专栏:生信情报站生信情报站
运行总次数:0
代码可运行

文章目录

零、视图家族

Django REST framework 为了方便视图类的操作,构建了包括以下几种视图类和工具集:

  • views:API视图
  • generics:工具视图
  • mixins:视图工具集
  • viewsets:视图集

一、GenericAPIView:视图家族的基类

generics.py 中的 GenericAPIView 作为视图家族中重要的基类,在后面的接口代码的实现中起到重要作用。

用 Pycharm 可以看到 GenericAPIView 的方法和继承关系:

GenericAPIView 继承自 APIView,使用兼容 APIView,也就是说依旧可以使用 get,post等方法。

但是,这里 GenericAPIView 封装了更多有趣的方法。

  • get_queryset(): 从类属性 queryset 中获得 model 的 queryset 数据
  • get_object(): 通过有名分组 pk 确定唯一操作对象 自定义主键的有名分组 :lookup_field = ‘id’
  • get_serializer():从类属性 serializer_class 中获得serializer 的序列化类

二、Mixins:视图工具集

mixins.py:视图工具集,用来辅助 GenericAPIView

包含有五个工具类文件,六个工具类方法:

  • CreateModeMixin:
    • **单增:**create
  • ListModelMixin:
    • **群查:**list
  • RetrieveModelMixin:
    • **单查:**retrieve
  • UpdateModelMixin:
    • **单整体改:**update
    • **单局部改:**partial_update
  • DestroyModelMixin:
    • **单删:**destroy,一般不使用该方法,或重写方法利用字段is_delete 来实现删除操作。

1.群查

查看源码
代码语言:javascript
代码运行次数:0
运行
复制
class ListModelMixin:
    """
    List a queryset.
    """
    def list(self, request, *args, **kwargs):
        # get_queryset 通过子类继承 GenericAPIView 得到
        queryset = self.filter_queryset(self.get_queryset())

        page = self.paginate_queryset(queryset)
        if page is not None:
            serializer = self.get_serializer(page, many=True)
            return self.get_paginated_response(serializer.data)

        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)
代码实现

继承工具类可以简化请求函数的实现体,但是必须继承 GenericAPIView,因为需要 GenericAPIView 提供类属性和方法。

工具类方法返回值是 Response 对象,可以用 response.data 拿到,扔给之前封装的APIResponse 类实现格式。

views.py

代码语言:javascript
代码运行次数:0
运行
复制
class BookListGenericAPIView(ListModelMixin, GenericAPIView):
    queryset = models.Book.objects.filter(is_delete=False)
    serializer_class = serializers.BookModelSerializer

    def get(self, request, *args, **kwargs):
        # 调用 ListModelMixin 的 list方法
        response = self.list(request, *args, **kwargs)
        # 添加自己封装的 APIResponse
        return APIResponse(results=response.data)

urls.py

代码语言:javascript
代码运行次数:0
运行
复制
from django.conf.urls import url

from api import views

urlpatterns = [
    url(r'^v3/books/$', views.BookListGenericAPIView.as_view()),
    url(r'^v3/books/(?P<pk>.*)/$', views.BookListGenericAPIView.as_view()),
]
测试接口

2.单查

查看源码
代码语言:javascript
代码运行次数:0
运行
复制
class RetrieveModelMixin:
    """
    Retrieve a model instance.
    """
    def retrieve(self, request, *args, **kwargs):
        instance = self.get_object()
        serializer = self.get_serializer(instance)
        return Response(serializer.data)
代码实现
代码语言:javascript
代码运行次数:0
运行
复制
class BookListGenericAPIView(ListModelMixin, RetrieveModelMixin, GenericAPIView):
    queryset = models.Book.objects.filter(is_delete=False)
    serializer_class = serializers.BookModelSerializer

    def get(self, request, *args, **kwargs):
        if 'pk' in kwargs:
            response = self.retrieve(request, *args, **kwargs)
        else:
            response = self.list(request, *args, **kwargs)
        return APIResponse(results=response.data)
测试接口

3.单增

查看源码

查看 CreateModelMixin 源码

代码语言:javascript
代码运行次数:0
运行
复制
class CreateModelMixin:
    """
    Create a model instance.
    """
    def create(self, request, *args, **kwargs):
        # 序列化
        serializer = self.get_serializer(data=request.data)
        # 验证
        serializer.is_valid(raise_exception=True)
        # 表单数据重建,函数名有语义,而直接调用逻辑是无意义的
        self.perform_create(serializer)
        # 设置 header
        headers = self.get_success_headers(serializer.data)
        return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)

    def perform_create(self, serializer):
        serializer.save()

    def get_success_headers(self, data):
        try:
            return {'Location': str(data[api_settings.URL_FIELD_NAME])}
        except (TypeError, KeyError):
            return {}
代码实现

可以看到这个类就是把之前单增的方法封装在一起方便调用

代码语言:javascript
代码运行次数:0
运行
复制
class BookListGenericAPIView(ListModelMixin, CreateModelMixin, GenericAPIView):
    queryset = models.Book.objects.filter(is_delete=False)
    serializer_class = serializers.BookModelSerializer

    def post(self, request, *args, **kwargs):
        response = self.create(request, *args, **kwargs)
        return APIResponse(results=response.data)
测试接口

4.单改

查看源码
代码语言:javascript
代码运行次数:0
运行
复制
class UpdateModelMixin:
    """
    Update a model instance.
    """
    # 实现单整体改
    def update(self, request, *args, **kwargs):
        partial = kwargs.pop('partial', False)
        instance = self.get_object()
        serializer = self.get_serializer(instance, data=request.data, partial=partial)
        serializer.is_valid(raise_exception=True)
        self.perform_update(serializer)

        if getattr(instance, '_prefetched_objects_cache', None):
            # If 'prefetch_related' has been applied to a queryset, we need to
            # forcibly invalidate the prefetch cache on the instance.
            instance._prefetched_objects_cache = {}

        return Response(serializer.data)

    def perform_update(self, serializer):
        serializer.save()
	
    # 单局部改,调用 update 设置 partial = True
    def partial_update(self, request, *args, **kwargs):
        kwargs['partial'] = True
        return self.update(request, *args, **kwargs)
代码实现
代码语言:javascript
代码运行次数:0
运行
复制
class BookListGenericAPIView(ListModelMixin, UpdateModelMixin, GenericAPIView):
    queryset = models.Book.objects.filter(is_delete=False)
    serializer_class = serializers.BookModelSerializer

    def put(self, request, *args, **kwargs):
        response = self.update(request, *args, **kwargs)
        return APIResponse(results=response.data)

    def patch(self, request, *args, **kwargs):
        response = self.partial_update(request, *args, **kwargs)
        return APIResponse(results=response.data)
测试接口

修改成功

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020/05/19 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 文章目录
  • 零、视图家族
  • 一、GenericAPIView:视图家族的基类
  • 二、Mixins:视图工具集
    • 1.群查
    • 2.单查
    • 3.单增
    • 4.单改
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档