Bob's Blog

Web开发、测试框架、自动化平台、APP开发、机器学习等

返回上页首页

Django restframework加Vue打造前后端分离的网站(三)在View中自定义API



前一篇写了新建一个简单的api,在这篇会记录一下在view中写自定义api的4种方法。

比如我们还是用上一篇的project对象,需要能展示project列表和具体一个project信息,project可以新加、修改,但不应该被删除掉。

第一种

通用型,适用于有model的对象,使用ModelViewSet,会包含所有可用的api方法。如果需要自定义比如禁用delete,则可以重写这个方法。

from .models import Project
from .serializers import ProjectSerializer
from rest_framework import viewsets


class ProjectViewSet(viewsets.ModelViewSet):

    queryset = Project.objects.all()
    serializer_class = ProjectSerializer

    # 如果想禁用某一个方法,可以类似如下,但不如用generics.RetrieveUpdateAPIView
    def destroy(self, request, *args, **kwargs):
        return Response({"message": "delete action is not allowed", "code": "200"}, status=status.HTTP_200_OK)

使用这种方法,不需要在app内添加url.py。但是在项目的url.py中需要加入下面几行

from projects.views import ProjectViewSet

router = routers.DefaultRouter()
router.register(r'projects', ProjectViewSet)

urlpatterns = [
    path('api/', include(router.urls)),
    ...
]

 

第二种

使用APIView。这种的代码量会多一点,但如果引入了第三方比如支付相关的,没有具体的业务对象在model中定义,那么这种会比较适合一点。

from django.http import Http404
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status


class ProjectList(APIView):
    # 定义 GET 请求的方法,内部实现相同 @api_view
    def get(self, request):
        projects = Project.objects.all()
        serializer = ProjectSerializer(projects, many=True)
        return Response(serializer.data, status=status.HTTP_200_OK)

    # 定义 POST 请求的方法
    def post(self, request):
        serializer = ProjectSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)


class ProjectDetail(APIView):

    def get_object(self, pk):
        try:
            return Project.objects.get(pk=pk)
        except Project.DoesNotExist:
            raise Http404

    def get(self, request, pk):
        project = self.get_object(pk)
        serializer = ProjectSerializer(project)
        return Response(serializer.data)

    def put(self, request, pk):
        project = self.get_object(pk)
        serializer = ProjectSerializer(project, data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    ## to permit delete action or not
    # def delete(self, request, pk):
    #     project = self.get_object(pk)
    #     project.delete()
    #     return Response(status=status.HTTP_204_NO_CONTENT)

除了第一种,剩下的都需要添加app内url.py,并修改项目url.py。

# url.py in app
from django.urls import path
from . import views

urlpatterns = [
    path('', views.ProjectList.as_view(), name='project_list'),
    path(r'<int:pk>/', views.ProjectDetail.as_view(), name='project_detail'),
]


# url.py in your web project
urlpatterns = [
    ...
    path('api/projects/', include('projects.urls')),
    ...
]

 

第三种

使用mixins。继承不同的mixins便可以获得不同的http方法,比如CreateModelMixin可以使用post,UpdateModelMixin可以使用put。

from rest_framework import mixins
from rest_framework import generics


class ProjectList(mixins.ListModelMixin,
                  mixins.CreateModelMixin,
                  mixins.UpdateModelMixin,
                  generics.GenericAPIView):
    # 指定列表
    queryset = Project.objects.all()
    # 指定序列化类
    serializer_class = ProjectSerializer

    def get(self, request, *args, **kwargs):
        # list 方法继承 ListModelMixin 而来
        return self.list(self, request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        # create 方法继承 CreateModelMixin 而来
        return self.create(self, request, *args, **kwargs)


# detail 视图通过 mixins 和 generics 改造
class ProjectDetail(mixins.RetrieveModelMixin,
                    mixins.UpdateModelMixin,
                    mixins.DestroyModelMixin,
                    generics.GenericAPIView):
    queryset = Project.objects.all()
    serializer_class = ProjectSerializer

    def get(self, request, *args, **kwargs):
        return self.retrieve(self, request, *args, **kwargs)

    def put(self, request, *args, **kwargs):
        return self.update(self, request, *args, **kwargs)

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

 

第四种

只使用generics,代替了mixins的功能。这种代码量最少。比如我希望包含get/put/delete则可以继承generics.RetrieveUpdateDestroyAPIView;如果我只希望有get/put不包含delete,那么可以继承generics.RetrieveUpdateAPIView。

from rest_framework import generics


class ProjectList(generics.ListCreateAPIView):
    queryset = Project.objects.all()
    serializer_class = ProjectSerializer


# class ProjectDetail(generics.RetrieveUpdateDestroyAPIView):
class ProjectDetail(generics.RetrieveUpdateAPIView):
    queryset = Project.objects.all()
    serializer_class = ProjectSerializer

不得不说,django restframework实在是好用方便。

下一篇:  Django restframework加Vue打造前后端分离的网站(四)生成接口文档
上一篇:  Django restframework加Vue打造前后端分离的网站(二)新建模块

共有0条评论

添加评论

暂无评论