12_04、视图组件

一、APIView

APIView继承了View

是drf的顶层视图,上一节就是利用APIView写的五个接口

from rest_framework.views import APIView

APIView的类属性

  renderer_classes
  parser_classes

APIView与View对比

get方法,post方法,delete方法写法跟之前的View一样,只不过request对象变成了新的reques对象
比之前的View多了三大认证和全局异常处理

二、GenericAPIView

GenericAPIView,继承了APIView  ,多了属性和方法

from rest_framework.generics import GenericAPIView

GenericAPIView的重要属性

queryset = None
serializer_class = None

GenericAPIView的重要方法

get_queryset
get_object
get_serializer

利用GenericAPIView写出五个接口

复制代码
# 第二层:继承GenericAPIView写视图类
from rest_framework.generics import GenericAPIView


class PublishView(GenericAPIView):
    queryset = Publish.objects.all()
    serializer_class = PublishSerialzier

    def get(self, request):
        # obj = self.queryset
        obj = self.get_queryset()  # 等同于上面,更好一些
        # ser = self.serializers(instance=obj,many=True)
        # ser=self.get_serializer_class()(instance=obj,many=True) # 等同于上面
        ser = self.get_serializer(instance=obj, many=True)  # 等同于上面
        return Response(ser.data)

    def post(self, request):
        # ser = BookSerializer(data=request.data)
        ser = self.get_serializer(data=request.data)  # 等同于上面
        if ser.is_valid():
            ser.save()
            return Response({"code": 100, 'msg': '新增成功', 'data': ser.data})
        return Response({"code": 101, 'msg': '新增出错', 'err': ser.errors})


class PublishDetailView(GenericAPIView):
    queryset = Publish.objects.all()
    serializer_class = PublishSerialzier

    # lookup_field = 'pk'
    def get(self, request, *args, **kwargs):
        # book = Book.objects.all().filter(pk=pk).first()
        obj = self.get_object()  # 等同于上面
        # ser = BookSerializer(instance=book)
        ser = self.get_serializer(instance=obj)  # 等同于上面
        return Response(ser.data)

    def put(self, request, *args, **kwargs):
        # book = Book.objects.all().filter(pk=pk).first()
        obj = self.get_object()  # 等同于上面
        # ser = BookSerializer(instance=book, data=request.data)
        ser = self.get_serializer(instance=obj, data=request.data)  # 等同于上面
        if ser.is_valid():
            ser.save()
            return Response({"code": 100, 'msg': '修改成功', 'data': ser.data})
        return Response({"code": 101, 'msg': '修改出错', 'err': ser.errors})

    def delete(self, request, *args, **kwargs):
        # Book.objects.filter(pk=pk).delete()
        self.get_object().delete()
        return Response({"code": 100, 'msg': '删除成功'})
View Code
复制代码

 路由

复制代码
from django.contrib import admin
from django.urls import path
from app01 import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('publishs/', views.PublishView.as_view()),
    path('publishs/<int:pk>', views.PublishDetailView.as_view()),
]
View Code
复制代码

三、5个视图扩展类

5个视图扩展类不是视图类,没有继承APIView,需要配合GenericAPIView

目的在于进一步方便我们编写五个接口

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

利用5个视图扩展类和GenericAPIView,写出五个接口

复制代码
## 第三层:GenericAPIView+5个视图扩展类
from rest_framework.generics import GenericAPIView
from rest_framework.mixins import CreateModelMixin, ListModelMixin, DestroyModelMixin, RetrieveModelMixin, \
    UpdateModelMixin


class PublishView(GenericAPIView, CreateModelMixin, ListModelMixin):
    queryset = Publish.objects.all()
    serializer_class = PublishSerialzier

    def get(self, request):
        return super().list(request)  # create(request)ListModelMixin的方法

    def post(self, request):
        return super().create(request)  # create(request)CreateModelMixin的方法


class PublishDetailView(GenericAPIView, UpdateModelMixin, RetrieveModelMixin, DestroyModelMixin):
    queryset = Publish.objects.all()
    serializer_class = PublishSerialzier

    # lookup_field = 'pk'
    def get(self, request, *args, **kwargs):
        return super().retrieve(request, *args, **kwargs)

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

    def delete(self, request, *args, **kwargs):
        return super().destroy(request, *args, **kwargs)
View Code
复制代码

四、9个视图子类

9个视图子类,是通过对GenericAPIView和5个视图扩展类进一步封装后,产生的新的视图类

from rest_framework.generics import CreateAPIView, ListAPIView, DestroyAPIView, RetrieveAPIView, UpdateAPIView
from rest_framework.generics import ListCreateAPIView,RetrieveUpdateAPIView, RetrieveUpdateDestroyAPIView,RetrieveDestroyAPIView

9个视图子类就是九种接口

注意,实际项目中,我们可能会通过重写get、post或其他方法,提高接口的扩展性

复制代码
  CreateAPIView,  # 新增一个
  ListAPIView,  # 查询所有
  DestroyAPIView,  # 删除一个
  RetrieveAPIView,  # 查询一个
  UpdateAPIView  # 修改一个
ListCreateAPIView, # 查询所有、新增一个 RetrieveUpdateAPIView, # 查询单条、更新 RetrieveUpdateDestroyAPIView, # 查询单条、更新、删除 RetrieveDestroyAPIView # 查询单条、删除
复制代码

利用9个视图子类写九个接口

复制代码
# 第四层:通过9个视图子类,编写视图函数
from rest_framework.generics import CreateAPIView, ListAPIView, DestroyAPIView, RetrieveAPIView, UpdateAPIView
from rest_framework.generics import ListCreateAPIView, RetrieveUpdateAPIView, RetrieveUpdateDestroyAPIView, \
    RetrieveDestroyAPIView


# class PublishView(ListCreateAPIView):  # 查询所有和新增接口就有了
# class PublishView(CreateAPIView):  # 新增接口就有了
class PublishView(ListAPIView):  # 查询所有接口就有了
    queryset = Publish.objects.all()
    serializer_class = PublishSerialzier

    # 有可能要重写--》get_queryset--》get_serializer_class--》perform_create--》get,post方法
    # 提高扩展性


class PublishDetailView(RetrieveUpdateDestroyAPIView):  # 查询单条,删除,修改
    # class PublishDetailView(RetrieveAPIView): # 查询单条
    # class PublishDetailView(DestroyAPIView): # 删除
    # class PublishDetailView(UpdateAPIView): # 修改
    # class PublishDetailView(RetrieveDestroyAPIView): # 查询单条和删除
    # class PublishDetailView(RetrieveUpdateAPIView): # 查询单条和更新
    # class PublishDetailView(UpdateAPIView,DestroyAPIView): # 更新和删除,这个没有提供,我们自己组合
    queryset = Publish.objects.all()
    serializer_class = PublishSerialzier
View Code
复制代码

五、ViewSet

第一层,通过继承APIView,写出5个接口

第二层,通过继承GenericAPIView,写出5个接口,封装了第一层的类属性,简化了类方法

第三层,通过五个视图扩展类,配合第二层的GenericAPIView,写出5个接口,进一步简化类方法

第四层,通过9个视图子类,细化出了九种接口,我们可以根据需要自行选择其中一种或多种

第五层,就是VIewSet,通过一个视图类,可以写出全部的5个接口

from rest_framework.viewsets import ModelViewSet  # 5个接口
from rest_framework.viewsets import ReadOnlyModelViewSet  # 查询单个和所有接口
# 二者同级

利用一个ViewSet写出所有接口(ModelViewSet、ReadOnlyModelViewSet)

class PublishView1(ModelViewSet):  # 5个接口
    queryset = Publish.objects.all()
    serializer_class = PublishSerialzier

class PublishView2(ReadOnlyModelViewSet):  # 查所有,查单个(需要修改路由)
    queryset = Publish.objects.all()
    serializer_class = PublishSerialzier

需要注意的是,虽然我们通过一个视图写了五个接口,但是这里面有两个get(查询一个、查询所有),所以这里需要我们重新配置路由

这里提供两种路由配置方式

方式一:

复制代码
from django.contrib import admin
from django.urls import path, include
from app01 import views

from rest_framework.routers import SimpleRouter, DefaultRouter

# router = DefaultRouter()
router = SimpleRouter()
router.register('publish', views.PublishView, 'publish')
router.register('test', views.TestView, 'test')

urlpatterns = [
    path('admin/', admin.site.urls),
    # 方式1 (这种方式方便我们定制路由写法)
    path('api/v1/', include(router.urls)),
    # 等同于下面
    # path('api/v1/publish/', views.BookView.as_view()),
    # path('api/v1/publish/<int:pk>', views.BookView.as_view()),
]
View Code
复制代码

方式二:

复制代码
from django.contrib import admin
from django.urls import path, include
from app01 import views

from rest_framework.routers import SimpleRouter, DefaultRouter

# router = DefaultRouter()
router = SimpleRouter()
router.register('publish', views.PublishView, 'publish')
router.register('test', views.TestView, 'test')

urlpatterns = [
    path('admin/', admin.site.urls),
]
# 方式二
# 把路由加入到urlpatterns的列表中
urlpatterns += router.urls  # 两个列表相加
# router.urls 他会自动生成列表 publishs/和publishs/<int:pk>
View Code
复制代码

补充:自动生成路由ViewSetMixin

之前我们手动配置路由,通过ViewSetMixin可以控制自动生成路由

所以以后只要想自动生成路由,必须继承ViewSetMixin及其子类

ViewSetMixin的子类:ViewSet,GenericViewSet

ViewSet=APIView+ViewSetMixin
GenericViewSet=GenericAPIView+ViewSetMixin
# 之前的写法可以沿用,只是如果要自动生成路由可以选择继承ViewSet,GenericViewSet
from rest_framework.viewsets import ViewSet,GenericViewSet
from rest_framework.viewsets import ViewSetMixin

 

posted @   三三得九86  阅读(30)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示