Django REST framework(六)-视图之APIVIEW基本视图类,GenericAPIView通用视图类
五个视图扩展类:
rest_framework.mixins.*
作用:
1、提供了增删改查几种后端视图逻辑代码处理流程的实现,如果需要编写的视图属于这五种,则视图可以通过继承相应的扩展类来复用代码,减少自己编写的代码量。
2、这五个扩展类需要搭配GenericAPIView通用视图基类,因为五个扩展类的实现需要调用GenericAPIView提供的序列化器与数据库查询的方法。
下面代码用到的序列化器
from rest_framework.serializers import ModelSerializer
from rest_framework import serializers
from book.models import BookInfo
class BookSerializer(ModelSerializer):
commentcount = serializers.IntegerField(max_value=10000, min_value=0, default=0)
readcount = serializers.IntegerField(max_value=10000, min_value=0, default=0)
class Meta:
model = BookInfo
fields = '__all__'
extra_kwargs = {
'is_delete': {
"write_only": True,
"read_only": False
},
'id': {
"write_only": True,
"read_only": False,
"required": False
}
}
下面代码所用到的模型类
# 准备书籍列表信息的模型类
class BookInfo(models.Model):
# 创建字段,字段类型...
name = models.CharField(max_length=20, verbose_name='名称')
pub_date = models.DateField(verbose_name='发布日期', null=True)
readcount = models.IntegerField(default=0, verbose_name='阅读量')
commentcount = models.IntegerField(default=0, verbose_name='评论量')
is_delete = models.BooleanField(default=False, verbose_name='逻辑删除')
class Meta:
db_table = 'bookinfo' # 指明数据库表名
verbose_name = '图书' # 在admin站点中显示的名称
def __str__(self):
"""定义每个数据对象的显示信息"""
return self.name
数据库数据
insert into bookinfo(name, pub_date, readcount,commentcount, is_delete) values
('射雕英雄传', '1980-5-1', 12, 34, 0),
('天龙八部', '1986-7-24', 36, 40, 0),
('笑傲江湖', '1995-12-24', 20, 80, 0),
('雪山飞狐', '1987-11-11', 58, 24, 0);
一、ListModelMixin
rest_framework.mixins.ListModelMixin
1、源代码
作用:列表视图扩展类,提供list(request, *args, **kwargs)
方法快速实现列表视图,返回200状态码。该Mixin的list方法会对数据进行过滤和分页。
class ListModelMixin:
"""
List a queryset.
"""
def list(self, request, *args, **kwargs):
# 过滤、调用GenericAPIView中的get_queryset()、filter_queryset方法获取过滤后的查询的所有数据
queryset = self.filter_queryset(self.get_queryset())
# 分页、调用GenericAPIView中的paginate_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)
2、案例
# 视图
class ListApiView(GenericAPIView, ListModelMixin):
serializer_class = BookSerializer
queryset = BookInfo.objects
def get(self, request):
# 调用ListModelMixin中的list方法
return self.list(request)
# 路由
path('demo/listview/', ListApiView.as_view())
二、CreateModelMixin
rest_framework.mixins.CreateModelMixin
作用:创建视图扩展类,提供create(request, *args, **kwargs)
方法快速实现创建资源的视图,成功返回201状态码。如果序列化器对前端发送的数据验证失败,返回400错误。
1、源代码
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)
# 调用save方法新建数据对象
self.perform_create(serializer)
# 设置响应头
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 {}
2、案例
# 视图
class CreateApiView(GenericAPIView, CreateModelMixin):
serializer_class = BookSerializer
queryset = BookInfo.objects
def post(self, request):
return self.create(request)
# 路由
path('demo/createview/', CreateApiView.as_view()),
三、RetrieveModelMixin
rest_framework.mixins.RetrieveModelMixin
作用: 通过url路径参数查询某个模型对象返回该模型对象的数据,如果存在,返回200, 否则返回404。
1、源代码
class RetrieveModelMixin:
"""
Retrieve a model instance.
"""
def retrieve(self, request, *args, **kwargs):
# 通过url路径参数查询某个模型对象
instance = self.get_object()
# 实例化序列化器
serializer = self.get_serializer(instance)
# 返回响应
return Response(serializer.data)
2、案例
# 视图
class RetrieveApiView(GenericAPIView, RetrieveModelMixin):
serializer_class = BookSerializer
queryset = BookInfo.objects
def get(self, request, pk):
return self.retrieve(request)
# 路由
re_path(r'^demo/retrieveview/(?P<pk>\d+)/$', RetrieveApiView.as_view()),
四、UpdateModelMixin
rest_framework.mixins.UpdateModelMixin
作用:更新视图扩展类,提供update(request, *args, **kwargs)
方法,可以快速实现更新一个存在的数据对象。同时也提供partial_update(request, *args, **kwargs)
方法,可以实现局部更新。成功返回200,序列化器校验数据失败时,返回400错误。
1、源代码
class UpdateModelMixin:
"""
Update a model instance.
"""
def update(self, request, *args, **kwargs):
partial = kwargs.pop('partial', False)
# 通过url路径参数查询某个模型对象
instance = self.get_object()
# 实例化序列化器
serializer = self.get_serializer(instance, data=request.data, partial=partial)
# 验证前端数据
serializer.is_valid(raise_exception=True)
# 调用save方法更新模型对象的数据
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)
2、案例
# 视图
class UpdateApiView(GenericAPIView, UpdateModelMixin):
serializer_class = BookSerializer
queryset = BookInfo.objects
def put(self, request, pk):
return self.update(request)
# 路由
re_path(r'^demo/updateview/(?P<pk>\d+)/$', UpdateApiView.as_view()),
五、DestroyModelMixin
rest_framework.mixins.DestroyModelMixin
作用:删除视图扩展类,提供destroy(request, *args, **kwargs)
方法,可以快速实现删除一个存在的数据对象。成功返回204,不存在返回404。
1、源代码
class DestroyModelMixin:
"""
Destroy a model instance.
"""
def destroy(self, request, *args, **kwargs):
# 通过url路径参数查询某个模型对象
instance = self.get_object()
# 删除模型对象
self.perform_destroy(instance)
return Response(status=status.HTTP_204_NO_CONTENT)
def perform_destroy(self, instance):
instance.delete()
2、案例
# 视图
class DestroyApiView(GenericAPIView, DestroyModelMixin):
queryset = BookInfo.objects
def delete(self, request, pk):
return self.destroy(request)
# 路由
re_path(r'^demo/deleteview/(?P<pk>\d+)/$', DestroyApiView.as_view()),
六、总结
1、整合代码(相比在之前代码中写的)
现在的
# 视图
class BooksMixinsView(GenericAPIView, ListModelMixin, CreateModelMixin):
serializer_class = BookSerializer
queryset = BookInfo.objects
def get(self, request):
"""获取所有模型对象数据"""
return self.list(request)
def post(self, request):
"""创建模型对象数据"""
return self.create(request)
class BookMixinsView(GenericAPIView, DestroyModelMixin, RetrieveModelMixin, UpdateModelMixin):
serializer_class = BookSerializer
queryset = BookInfo.objects
def get(self, request, pk):
"""获取单一模型对象数据"""
return self.retrieve(request, pk=pk)
def delete(self, request, pk):
"""删除单一模型对象数据"""
return self.destroy(request, pk=pk)
def put(self, request, pk):
"""修改单一模型对象数据"""
return self.update(request, pk=pk)
#路由
path('demo/books/', BooksMixinsView.as_view()),
re_path(r'^demo/books/(?P<pk>\d+)/$', BookMixinsView.as_view()),
之前的 (Django REST framework(六)-视图之APIVIEW基本视图类,GenericAPIView通用视图类)
class BookGenericAPIView(GenericAPIView):
queryset = BookInfo.objects
serializer_class = BookSerializer
def get(self, request, pk):
"""获取单一图书信息"""
book = self.get_object() # 该方法自动获取路径参数pk查询某一模型对象
ser = self.get_serializer(instance=book)
data = ser.data
return Response(data=data, status=status.HTTP_200_OK)
def put(self, request, pk):
book = self.get_object()
ser = self.get_serializer(instance=book, data=request.data)
if ser.is_valid() is False:
return Response(data=ser.errors, status=status.HTTP_424_FAILED_DEPENDENCY)
ser.save()
data = ser.data
return Response(data=data, status=status.HTTP_200_OK)
def delete(self, request, pk):
self.get_object().delete()
return Response('删除成功', status=status.HTTP_200_OK)
class BooksGenericAPIView(GenericAPIView):
# 多个序列化器的情况
# def get_serializer_class(self):
# if self.request.method.lower() == "put":
# return Serializer1
# else:
# return Serializer2
# 单个序列化器的情况
serializer_class = BookSerializer
queryset = BookInfo.objects
def get(self, request):
"""返回所有图书信息"""
books = self.get_queryset()
ser = self.get_serializer(instance=books, many=True)
data = ser.data
return Response(data=data, status=status.HTTP_200_OK)
def post(self, request):
"""增加一个新的图书信息"""
ser = self.get_serializer(data=request.data)
if ser.is_valid() is False:
return Response(data=ser.errors)
ser.save()
data = ser.data
return Response(data=data, status=status.HTTP_200_OK)
测试
2、总结
相比于GenericAPIView:
- 五个扩展类基于GenericAPIView的基础上实现代码的封装
- 五个扩展类只是对于增删改查进行了代码封装,并未实现as_view()等View的相关的方法,所以不能单独用于视图,需要和GenericAPIView相互配合使用
- 五个扩展类视图只需要在继承之后定义查询集对象和序列化器后,再调用相应的方法即可使用。