drf视图集学习

1. 五个视图扩展类和GenericAPIView的视图子类: 

提供了几种后端视图(对数据资源进行曾删改查)处理流程的实现,如果需要编写的视图属于这五种,则视图可以通过继承相应的扩展类来复用代码,减少自己编写的代码量。这五个扩展类需要搭配GenericAPIView父类,因为五个扩展类的实现需要调用GenericAPIView提供的序列化器与数据库查询的方法。

 urls.py

from django.urls import path, re_path
from . import views

urlpatterns = [
    path("student/", views.StudentAPIView.as_view()),
    re_path("^student2/(?P<pk>d+)/$", views.Student2APIView.as_view()),
    path("student3/", views.Student3APIView.as_view()),
    re_path("^student4/(?P<pk>d+)/$", views.Student4APIView.as_view()),
]

serializers.py

from rest_framework import serializers
from students import models


class StudentModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Student
        fields = "__all__"

views.py

from .serializers import StudentModelSerializer
from students import models

from rest_framework.mixins import ListModelMixin, CreateModelMixin, UpdateModelMixin, DestroyModelMixin, RetrieveModelMixin
from rest_framework.generics import GenericAPIView


class StudentAPIView(GenericAPIView, ListModelMixin, CreateModelMixin):
    serializer_class = StudentModelSerializer
    queryset = models.Student.objects

    # 获取多条数据
    def get(self, request):
        return self.list(request)

    # 提交数据
    def post(self, request):
        return self.create(request)


class Student2APIView(GenericAPIView, UpdateModelMixin, DestroyModelMixin, RetrieveModelMixin):
    serializer_class = StudentModelSerializer
    queryset = models.Student.objects

    # 修改一条数据
    def post(self, request, pk):
        return self.update(request, pk)

    # 查询一条数据
    def get(self, request, pk):
        return self.retrieve(request, pk)

    # 删除一条数据
    def delete(self, request, pk):
        return self.destroy(request, pk)

#
GenericAPIView的视图子类
from rest_framework.generics import ListAPIView, UpdateAPIView, CreateAPIView, DestroyAPIView, RetrieveAPIView, RetrieveUpdateDestroyAPIView

class Student3APIView(ListAPIView, CreateAPIView):
    serializer_class = StudentModelSerializer
    queryset = models.Student.objects

# class Student4APIView(UpdateAPIView, DestroyAPIView, RetrieveAPIView):
class Student4APIView(RetrieveUpdateDestroyAPIView):
    serializer_class = StudentModelSerializer
    queryset = models.Student.objects

2. 视图集Viewset :

使用视图集ViewSet,可以将一系列逻辑相关的动作放到一个类中:
list() 提供一组数据
retrieve() 提供单个数据
create() 创建数据
update() 保存数据
destory() 删除数据
ViewSet视图集类不再实现get()、post()等方法,而是实现动作 action 如 list() 、create() 等。
视图集只在使用as_view()方法的时候,才会将action动作与具体请求方式对应上

视图集GenericViewSet :

使用ViewSet通常并不方便,因为list、retrieve、create、update、destory等方法都需要自己编写,而这些方法与前面讲过的Mixin扩展类提供的方法同名,
所以我们可以通过继承Mixin扩展类来复用这些方法而无需自己编写。但是Mixin扩展类依赖与`GenericAPIView`,所以还需要继承`GenericAPIView`。 GenericViewSet就帮助我们完成了这样的继承工作,继承自`GenericAPIView`与`ViewSetMixin`,
在实现了调用as_view()时传入字典(如`{
'get':'list'}`)的映射处理工作的同时,还提供了`GenericAPIView`提供的基础方法,可以直接搭配Mixin扩展类使用。

视图集ModelViewSet :

继承自`GenericViewSet`,同时包括了ListModelMixin、RetrieveModelMixin、CreateModelMixin、UpdateModelMixin、DestoryModelMixin。

ReadOnlyModelViewSet:

继承自`GenericViewSet`,同时包括了ListModelMixin、RetrieveModelMixin。

urls.py

from django.urls import path, re_path
from . import views

urlpatterns = [
    path("student/", views.StudentAPIViewSet.as_view({"get": "list", "post": "post"})),
    re_path("^student1/(?P<pk>d+)/$",views.StudentAPIViewSet.as_view({"get": "get", "put": "put", "delete": "delete"})),
    path("student2/", views.Student2APIViewSet.as_view({"get": "get", "post": "post"})),
    re_path("^student3/(?P<pk>d+)/$",views.Student2APIViewSet.as_view({"get": "get_one", "put": "put", "delete": "delete"})),
]

# 使用路由类给视图集生成路由
from rest_framework.routers import SimpleRouter, DefaultRouter
router = DefaultRouter()
# router.register("路由访问前缀","视图集类","路由别名")
router.register("student4", views.Student3APIViewSet, )
print(router.urls)
# 把路由类生成的路由信息合并到项目中
urlpatterns += router.urls

路由说明:

DefaultRouter与SimpleRouter的区别是,DefaultRouter会多附带一个默认的API根视图,返回一个包含所有列表视图的超链接响应数据。

views.py

from students import models
from learn.serializers import StudentModelSerializer

from rest_framework.viewsets import ViewSet
from rest_framework.response import Response
from rest_framework import status


class StudentAPIViewSet(ViewSet):
    def list(self,request):
        """获取多条数据"""
        student_list = models.Student.objects.all()
        serializer = StudentModelSerializer(instance=student_list,many=True)
        return Response(serializer.data)

    def post(self,request):
        """添加学生信息"""
        serialzier = StudentModelSerializer(data=request.data)
        serialzier.is_valid(raise_exception=True)
        serialzier.save()
        return Response(serialzier.data)

    def get(self,request,pk):
        """获取一条数据"""
        student = models.Student.objects.get(pk=pk)
        serializer = StudentModelSerializer(instance=student)
        return Response(serializer.data)

    def put(self,request,pk):
        student = models.Student.objects.get(pk=pk)
        serializer = StudentModelSerializer(instance=student, data=request.data)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        return Response(serializer.data)

    def delete(self,request,pk):
        models.Student.objects.get(pk=pk).delete()
        return Response(status=status.HTTP_204_NO_CONTENT)


from rest_framework.viewsets import GenericViewSet


# GenericViewSet视图集
class Student2APIViewSet(GenericViewSet):
    serializer_class = StudentModelSerializer
    queryset = models.Student.objects

    def get(self,request):
        """获取多条"""
        # serializer = self.serializer_class(instance=self.queryset.all(),many=True)
        serializer = self.get_serializer(instance=self.get_queryset(),many=True)
        return Response(serializer.data)

    def post(self,request):
        """添加信息"""
        serialzier = self.get_serializer(data=request.data,context={})
        serialzier.is_valid(raise_exception=True)
        serialzier.save()
        return Response(serialzier.data)

    def get_one(self,request,pk):
        """获取一条数据"""
        # serializer = self.serializer_class(instance=self.queryset.get(pk=pk))
        serializer = self.get_serializer(instance=self.get_object())
        return Response(serializer.data)

    def put(self,request,pk):
        serializer = self.get_serializer(instance=self.get_object(), data=request.data)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        return Response(serializer.data)

    def delete(self,request,pk):
        self.get_object().delete()
        return Response(status=status.HTTP_204_NO_CONTENT)


# modelviewset
from rest_framework.viewsets import ModelViewSet
from demo.serializers import Studnet2ModelSerializers


class Student3APIViewSet(ModelViewSet):
    serializer_class = StudentModelSerializer
    queryset = models.Student.objects
    
    def get_serializer_class(self):
        print(self.action)  # 通过action对象属性来获取当前请求视图集时的action动作是哪个。
        if self.action.lower() == "list":
            return StudentModelSerializer
        else:
            return Studnet2ModelSerializers

在视图集中自定义动作:

    """
    methods: 设置那些http请求方法能访问到当前视图方法
    detail: 设置生成路由时,是否附带id到地址中
        True:  <URLPattern '^student9/(?P<pk>[^/.]+)/test_api/$' [name='student-test-api']>
        False: <URLPattern '^student9/test_api/$' [name='student-test-api']>
    url_path: 设置访问当前方法的子路由,如果不配置,则默认是是当前方法名
    """
    @action(methods=["get","post"],detail=True)
    def test_api(self,request):
        return Response("测试数据")

 

原文地址:https://www.cnblogs.com/fdsimin/p/13612037.html