0
点赞
收藏
分享

微信扫一扫

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



文章目录


  • ​​零、视图家族​​
  • ​​一、GenericAPIView:视图家族的基类​​
  • ​​二、Mixins:视图工具集​​

  • ​​1.群查​​

  • ​​查看源码​​
  • ​​代码实现​​
  • ​​测试接口​​

  • ​​2.单查​​

  • ​​查看源码​​
  • ​​代码实现​​
  • ​​测试接口​​

  • ​​3.单增​​

  • ​​查看源码​​
  • ​​代码实现​​
  • ​​测试接口​​

  • ​​4.单改​​

  • ​​查看源码​​
  • ​​代码实现​​
  • ​​测试接口​​




零、视图家族

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


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

一、GenericAPIView:视图家族的基类

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

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

Django REST 框架详解 05  |  视图家族 Mixins_数据库

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

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

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


  • CreateModeMixin:
  • **单增:**create
  • ListModelMixin:
  • **群查:**list
  • RetrieveModelMixin:
  • **单查:**retrieve
  • UpdateModelMixin:

  • **单整体改:**update
  • **单局部改:**partial_update

  • DestroyModelMixin:
  • **单删:**destroy,一般不使用该方法,或重写方法利用字段is_delete 来实现删除操作。

1.群查

查看源码

Django REST 框架详解 05  |  视图家族 Mixins_网站_03

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​

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​

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()),
]
测试接口

Django REST 框架详解 05  |  视图家族 Mixins_后端_04

2.单查

查看源码

Django REST 框架详解 05  |  视图家族 Mixins_后端_05

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)
代码实现
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)
测试接口

Django REST 框架详解 05  |  视图家族 Mixins_数据库_06

3.单增

查看源码

Django REST 框架详解 05  |  视图家族 Mixins_数据库_07

查看 ​​CreateModelMixin​​ 源码

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 {}
代码实现

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

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)
测试接口

Django REST 框架详解 05  |  视图家族 Mixins_数据库_08

4.单改

查看源码
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)
代码实现
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)
测试接口

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

修改成功Django REST 框架详解 05  |  视图家族 Mixins_数据库_10



举报

相关推荐

0 条评论