DRF APIView、GenericAPIView、GenericAPIView与mixins结合的选择

179 阅读3分钟

简介

APIViewGenericAPIViewDjango Rest Framework中引入的视图类,而APIView是对原生Django View的封装,灵活运用APIViewGenericAPIView可以大幅度提升业务开发效率,而且大大提升了代码的可维护性,降低耦合度。

【APIView】
  1. 应用APIView的例子:
class StudentList(APIView):

    def get(self ,request ,format=None):
        stus = Student.objects.all()
        ser = StudentSerializer(stus,many=True)
        return Response(ser.data)
        
    def post(self ,request ,format=None):
        ser = StudentSerializer(data=request.data)
        # 验证数据,如果验证通过,则保存数据
        if ser.is_valid():
            ser.save()
        else:
            return Response(ser.errors,status=400)

class StudentDetail(APIView):
    
    def get(self,request,pk,format=None):
        # 查询单个数据
        try:
            stu = Student.objects.get(pk=pk)
        except Student.DoesNotExist:
            return Response({'error':'数据不存在'},status=404)   
            # 将数据转换为json格式
            ser = StudentSerializer(stu)
            return Response(ser.data,status=200)

    def put(self,request,pk,format=None):
        try:
            stu = Student.objects.get(pk=pk)
        except Student.DoesNotExist:
            return Response({'error':'数据不存在'},status=404)
        ser = StudentSerializer(stu,data=request.data)
        if ser.is_valid():
            ser.save()
            return Response(ser.data, status=status.HTTP_201_CREATED)
        else:
            return Response(ser.data, status=400)

    def delete(self,request,pk,format=None):
        try:
            stu = Student.objects.get(pk=pk)

        except Student.DoesNotExist:
            return Response({'error':'数据不存在'},status=404)
【GenericAPIView】
  1. 应用的例子:
class StudentList(GenericAPIView):
    # 指定查询集
    queryset = Student.objects.all()
    # 指定序列化器,不用创建对象
    serializer_class = StudentSerializer

    def get(self ,request ,format=None):

        # 查询所有数据
        stus = self.get_queryset()
        # 将数据转换成为json格式,stus是一个列表,many代表要转换的数据是一个列表
        ser = self.get_serializer(stus,many=True)
        return Response(ser.data)
        
    def post(self ,request ,format=None):
        ser = StudentSerializer(data=request.data)
        # 验证数据,如果验证通过,则保存数据
        if ser.is_valid():
            # 保留数据
            ser.save()
        else:
            # 验证失败,返回错误信息
            return Response(ser.errors,status=400)

class StudentDetail(GenericAPIView):
    # 指定查询集
    queryset = Student.objects.all()
    # 指定序列化器,不用创建对象
    serializer_class = StudentSerializer

    def get(self,request,pk,format=None):
        # 查询单个数据
        try:
            stu = self.get_object()
        except Student.DoesNotExist:
            return Response({'error':'数据不存在'},status=404)   
            # 将数据转换为json格式
        ser = self.get_serializer(stu)
   
        return Response(ser.data,status=200)

    def put(self,request,pk,format=None):
        try:
            stu = self.get_object()
        except Student.DoesNotExist:
            return Response({'error':'数据不存在'},status=404)
        ser = self.get_serializer(stu,data=request.data)
        # 验证数据,如果验证通过,则保存数据
        if ser.is_valid():
            ser.save()
            return Response(ser.data, status=status.HTTP_201_CREATED)
        else:
            # 验证失败,返回错误信息
            return Response(ser.data, status=400)

    def delete(self,request,pk,format=None):
        # 查询单个数据
        try:
            stu = Student.objects.get(pk=pk)
        except Student.DoesNotExist:
            return Response({'error':'数据不存在'},status=404)
            # 删除数据
        stu.delete()
        return Response(ser.data,status=200)
【GenericAPIView和minxins结合】
  1. 只想实现简单的增删改查ModelViewSet
  2. 只想增CreateModelMixin,GenericViewSet
  3. 只想增删改CreateModelMixin,DestroyModelMixin,UpdateModelMixin,GenericViewSet
  4. 如果视图中的业务逻辑复杂,以上都不能满足的时候,直接使用APIView
# 使用GenericAPIView类来实现,restframework的视图包装
class StudentList(mixins.ListModelMixin,mixins.CreateModelMixin,GenericAPIView):

    queryset = Student.objects.all()
    serializer_class = StudentSerializer

    def get(self ,request ,format=None):
        # 调用ListModelMixin类中的list方法
        return self.list(request,format=None)

    def post(self, request, format=None):
        print(request.data)
        return self.create(request,format=None)

class StudentDetail(mixins.RetrieveModelMixin,mixins.UpdateModelMixin,mixins.DestroyModelMixin,GenericAPIView):
    # 指定查询集
    queryset = Student.objects.all()
    # 指定序列化器
    serializer_class = StudentSerializer

    def get(self,request,pk,format=None):
        return self.retrieve(request,pk,format=None)
        
    def put(self,request,pk,format=None):
        return self.update(request,pk,format=None)

    def delete(self,request,pk,format=None):
        return self.destroy(request,pk,format=None)
【generics包下封装的mixin】
  1. 该包在rest_framework里面,该类应用起来比上面的一些View类更简洁,少写很多代码。
  2. 说明各个主要类继承于哪类
    • CreateAPIView提供 post 方法,继承自: GenericAPIView、CreateModelMixin
    • ListAPIView提供 get 方法,继承自:GenericAPIView、ListModelMixin
    • RetrieveAPIView提供 get 方法,继承自: GenericAPIView、RetrieveModelMixin
    • DestoryAPIView提供 delete 方法,继承自:GenericAPIView、DestoryModelMixin
    • UpdateAPIView提供 put 和 patch 方法,继承自:GenericAPIView、UpdateModelMixin
    • ListCreateAPIView提供 get 和 post 方法,继承自: GenericAPIView、ListModelMixin、CreateModelMixin
    • RetrieveUpdateAPIView 提供 get、put、patch方法, 继承自: GenericAPIView、RetrieveModelMixin、UpdateModelMixin
    • RetrieveDestroyAPIView 提供 get、delete 方法,继承自:GenericAPIView、RetrieveModelMixin、DestroyModelMixin
    • RetrieveUpdateDestoryAPIView 提供 get、put、patch、delete方法, 继承自:GenericAPIView、RetrieveModelMixin、UpdateModelMixin、DestoryModelMixin
  3. 应用generics的例子:
#views.py
from rest_app.models import Student
from rest_app.serializers import StudentSerializer
from rest_framework import generics

# 使用ListCreateAPIView来实现restframework的视图包装
class StudentList(generics.ListCreateAPIView):
    # 指定查询集
    queryset = Student.objects.all()
    # 指定序列化器
    serializer_class = StudentSerializer

class StudentDetail(generics.RetrieveUpdateDestroyAPIView):
    # 指定查询集
    queryset = Student.objects.all()
    # 指定序列化器
    serializer_class = StudentSerializer
    
#urls.py
from django.urls import path
from . import views

urlpatterns = [
    # 使用generics包下封装的mixin(扩展类)来实现restframework的视图包装
    path("student4/", pack_mixin_views.StudentList.as_view()), #查询所有数据,添加
    path("student4/<int:pk>/", pack_mixin_views.StudentDetail.as_view()) #查询单个数据,修改数据,删除数
]

--待完成