【Django】DRF(rest_framework)的视图相关

1.两个基类

1.1 APIView

(1)APIView继承于Django的View,是REST framework提供的所有视图的基类,request参数不是Django的HttpRequeset,而是在此基础上进行了拓展,
request.data:即Django的request.POST和 request.FILES
request.query_params:即Django的request.GET
Response(需另外导入):任何APIException异常都会被捕获到

1.2 GenericAPIView

GenericAPIView继承于APIView,增加一些比较常用的通用支持方法,一般可搭配一个或多个Mixin扩展类使用

支持定义的属性 说明
queryset 查询集
serializer_class 序列化器
lookup_field 查询单一数据的过滤字段,默认是pk
lookup_url_kwarg 查询单一数据的参数关键字名称,默认与lookup_field相同
pagination_class 分页控制类
filter_backends 过滤控制后端
方法 说明
get_queryset(self) 获取查询集
get_object(self) 获取单一模型类对象
get_serializer(self, *args, **kwargs) 获取实例化的序列化器对象
get_serializer_class(self) 获取序列化器类

以上方法一般配合定义的类属性使用,确保得到的是最新的结果(因为存在惰性和缓存)

举例

from rest_framework.generics import GenericAPIView
from rest_framework.response import Response
from .models import BookInfo
from .serializers import BookInfoModelSerializer

# re_path(r'^books/$',views.BooksView.as_view()),
class BooksView(GenericAPIView):
    queryset = BookInfo.objects.all()
    serializer_class = BookInfoModelSerializer

    # 获取列表资源:GET /books/
    def get(self,request):
        books = self.get_queryset() # 即返回类属性的查询集
        serializer = self.get_serializer(instance=books,many=True)
        return Response(data=serializer.data)

    # 新建单一资源:POST /books/
    def post(self,request):
        serializer = self.get_serializer(data=request.data)
        if not serializer.is_valid():
            return Response(data={
    
    "errmsg":"参数错误"},status=400)
        serializer.save()
        return Response(data=serializer.data)


# re_path(r'^book/(?P<pk>\d+)/$',views.BookView.as_view())
class BookView(GenericAPIView):
    queryset = BookInfo.objects.all()
    serializer_class = BookInfoModelSerializer

    # lookup_field = 'pk' # 该类属性默认值就是'pk' —— 默认唯一过滤依据'pk'字段
    # lookup_url_kwarg = lookup_field # 该类属性默认等于lookup_field —— 指定提取过滤字段值的分组名称

    # 获取单一资源:GET /books/1/
    def get(self,request, pk):
        book = self.get_object()  # 默认使用lookup_field参数来过滤queryset
        serializer = self.get_serializer(instance=book)
        return Response(data=serializer.data)

    # 更新单一资源(全更新):PUT /books/1/
    def put(self, request, pk):
        book =self.get_object()
        serializer = self.get_serializer(instance=book,data=request.data)
        if not serializer.is_valid():
            return Response(data={
    
    "errmsg":"参数错误"},status=400)
        serializer.save()
        return Response(data=serializer.data)

    # 更新单一资源(部分更新):PATCH /books/1/
    def patch(self,request, pk):
        book = self.get_object()
        serializer = self.get_serializer(instance=book,data=request.data)
        if not serializer.is_valid():
            return Response({
    
    "errmsg":"参数错误"},status=400)
        serializer.save()
        return Response(data=serializer.data)

    # 删除单一资源:DELETE /books/1/
    def delete(self,request,pk):
        book = self.get_object()
        book.delete()
        return Response(data=None,status=204)

2.五个扩展类

扩展类 说明
ListModelMixin 提供self.list方法,封装序列化多条模型类对象(列表数据) 返回的逻辑代码
CreateModelMixin 提供self.create方法,封装反序列化新建单一对象的逻辑代码
RetrieveModelMixin 提供self.retrieve方法,封装序列化返回单一资源的逻辑代码
UpdateModelMixin 提供self.update方法,封装反序列化全更新(全校验)单一资源的逻辑代码
提供self.partial_update方法,封装反序列化部分更新(部分校验)单一资源的逻辑代码
DestroyModelMixin 提供self.destroy方法,封装反序列化删除单一资源的逻辑代码

还是上面的代码,继承GenericAPIView,感觉写法太啰嗦了,我们可以继承五大拓展类,直接return封装好的方法,大大简化代码,改写如下

from rest_framework.generics import GenericAPIView
from rest_framework.mixins import ListModelMixin, CreateModelMixin, RetrieveModelMixin, UpdateModelMixin, \
    DestroyModelMixin
from .models import BookInfo
from .serializers import BookInfoModelSerializer

# re_path(r'^books/$',views.BooksView.as_view()),
class BooksView(ListModelMixin,CreateModelMixin,GenericAPIView):
    queryset = BookInfo.objects.all()
    serializer_class = BookInfoModelSerializer

    # 获取列表资源:GET /books/
    def get(self,request):
        return self.list(request)

    # 新建单一资源:POST /books/
    def post(self,request):
        return self.create(request)


# re_path(r'^book/(?P<pk>\d+)/$',views.BookView.as_view())
class BookView(RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin,GenericAPIView):
    queryset = BookInfo.objects.all()
    serializer_class = BookInfoModelSerializer

    # lookup_field = 'pk' # 该类属性默认值就是'pk' —— 默认唯一过滤依据'pk'字段
    # lookup_url_kwarg = lookup_field # 该类属性默认等于lookup_field —— 指定提取过滤字段值的分组名称

    # 获取单一资源:GET /books/1/
    def get(self,request, pk):
        return self.retrieve(request,pk)

    # 更新单一资源(全更新):PUT /books/1/
    def put(self, request, pk):
        return self.update(request,pk)

    # 更新单一资源(部分更新):PATCH /books/1/
    def patch(self,request, pk):
        return self.partial_update(request,pk)

    # 删除单一资源:DELETE /books/1/
    def delete(self,request,pk):
        return self.destroy(request,pk)

3.五个子类视图

视图 说明
ListAPIView 序列化返回列表资源
提供self.get视图方法,内部调用拓展视图self.list方法
CreateAPIView 反序列化新建单一资源
提供self.post视图方法,内部调用拓展视图self.create方法
RetrieveAPIView 序列化返回单一资源
提供self.get视图方法,内部调用拓展视图self.retrieve方法
UpdateAPIView 反序列化更新单一资源
提供self.put视图方法,内部调用拓展视图self.update方法
提供self.patch视图方法,内部调用拓展视图self.partial_update方法
DestroyAPIView 反序列化删除单一资源
提供self.delete视图方法,内部调用拓展视图self.destroy方法

还是上面的代码,继承五大扩展类的,但是代码还不够简洁,我们还可以把它进一步精简,就是通过继承五个子类视图省略用于路由的请求方法

from rest_framework.generics import ListAPIView, CreateAPIView, RetrieveAPIView, UpdateAPIView, \
    DestroyAPIView
from .models import BookInfo
from .serializers import BookInfoModelSerializer

# 原则:一类资源,尽可能使用一个类视图封装增删改查接口;
# 结论:Mixin几个拓展类中提供的方法定义是如何视图函数定义 —— 可以用来进行路由映射

# re_path(r'^books/$',views.BooksView.as_view()),
class BooksView(CreateAPIView,ListAPIView):
    queryset = BookInfo.objects.all()
    serializer_class = BookInfoModelSerializer

# re_path(r'^book/(?P<pk>\d+)/$',views.BookView.as_view())
class BookView(RetrieveAPIView,UpdateAPIView,DestroyAPIView):
    queryset = BookInfo.objects.all()
    serializer_class = BookInfoModelSerializer


4.视图集

视图 说明
ViewSetMixin 重写self.as_view()函数,传入字典指定请求方式映射的视图函数
ViewSet 继承ViewSetMixin和APIView
ModelViewSet 继承五大拓展类和GenericAPIView
GenericViewSet 继承ViewSetMixin和GenericAPIView
ReadOnlyModelViewSet 继承RetrieveModelMixin、ListModelMixin和GenericAPIView;提供只读接口

猜你喜欢

转载自blog.csdn.net/qq_39147299/article/details/108738435