十、REST framework接口开发:基于GenericAPIView接口实现

前言:

  使用GenericAPIView把代码逻辑中写死的变量全部参数化,后续如果想编写其他单表的接口时,只需要修改queryset和serializer_class,大大减少了代码的维护成本

实现:

1、针对复杂逻辑的接口,我们使用APIView进行接口开发,但是对于单表,DRF内部提供了自己的一套逻辑,APIView已经写过随笔,当前随笔,讲解GenericAPIView

请注意:之前我们重写了APIView方法,在使用GenericAPIView时,最好不要修改继承关系

下面的步骤,虽然最终版是ModelViewSet最好一步一步的跟着操作,有助于了解整个DRF的工作流程

 

APIView->GenericAPIView->mixins->ListCreateAPIView->ModelViewSet

 2、使用GenericAPIView实现接口的增删改查查

class CaseDataSerializer(serializers.ModelSerializer):

    class Meta:
        model = Interface_case_data
        fields = ["parent_id", "interface_case_name", "request_data", "request_expected_results"]

    # 重写父类的create方法
    def create(self, validated_data):
        # 获取数据库对象
        case_data = Interface_case_data.objects.create(**self.validated_data)
        return case_data

    # 重写父类的update方法
    def update(self, instance, validated_data):
        # pk=instance.pk 获取修改数据的主键
        Interface_case_data.objects.filter(pk=instance.pk).update(**validated_data)
        # 修改完成后,获取新数据进行返回
        updated_case = Interface_case_data.objects.get(pk=instance.pk)
        return updated_case


from rest_framework.generics import GenericAPIView


class RequestDataView(GenericAPIView):
    # 认证类,没有时为空
    authentication_classes = []
    permission_classes = []

    # GenericAPIView提供了两个变量分别是 queryset 和 serializer_class
    # queryset 存放数据使用
    queryset = Interface_case_data.objects.all()
    # 存放序列化器类
    serializer_class = CaseDataSerializer

    # 新建get方法
    def get(self, request, *args, **kwargs):
        # 使用 get_queryset 方法获取 queryset 的值
        queryset = self.get_queryset()
        # 使用 get_serializer 方法获取序列化器,并对序列化器进行操作
        ser = self.get_serializer(instance=queryset, many=True)
        # 返回序列化后的数据
        return Response(ser.data)

    # 新建post方法
    def post(self, request, *args, **kwargs):
        ser = self.get_serializer(data=request.data)
        # ser.is_valid(),校验字段方法,根据序列化器
        if ser.is_valid():
            ser.save()
            # ser.data为默认写法,数据从ser.data中获取,详细逻辑查看源码
            return Response(ser.data)
        else:
            # 当序列化错误时,错误信息字段写入ser.errors,如:字段过长等信息
            return Response(ser.errors)


class RequestDataDetailView(GenericAPIView):

    # 认证类,没有时,注释掉
    authentication_classes = []
    permission_classes = []

    queryset = Interface_case_data.objects.all()
    serializer_class = CaseDataSerializer
    # 结合get方法使用,默认值为lookup_field="pk"
    lookup_field = 'id'

    # 单查询
    def get(self, request, *args, **kwargs):
        # get_object 根据pk值获取对象,GenericAPIView内部定义了lookup_field=pk,默认通过url中的有名分组pk进行取值,有名分组在路由中可以查看
        # 如果想修改默认值,添加 lookup_field = xxx 即可
        ser = self.get_serializer(instance=self.get_object())  # 序列化
        return Response(ser.data)  # 返回

    # 单条数据更新,演示m2m数据更新,当没有m2m时,手动处理逻辑
    def put(self, request, *args, **kwargs):
        # 进行序列化
        ser = self.get_serializer(instance=self.get_object(), data=request.data)
        if ser.is_valid():  # 验证字段,注意:验证字段根据data进行验证
            # 根据save方法,当instance不为空时,调用update方法
            ser.save()
            return Response(ser.data)
        else:
            return Response(ser.errors)

    def delete(self, request, *args, **kwargs):
        self.get_object().delete()
        return Response()

 3、路由配置信息

urlpatterns = [
    path('api/<str:version>/user/', views.RequestDataView.as_view()),
    # 请注意:有名分组(?P<id>\d+),不过不想定义lookup_field = 'id',把id换成pk即可
    re_path("api/(?P<version>.+)/user/(?P<id>\d+)", views.RequestDataDetailView.as_view()),
]

 

posted @ 2025-01-02 11:22  蜗牛·哥  阅读(25)  评论(0)    收藏  举报