DRF 视图组件

DRF框架提供了很多通用的视图基类与扩展类,上篇使用的APIView是比较偏Base的,视图的使用更加简化了代码,这里介绍一下其他视图的用法

Django REST framwork 提供的视图的主要作用:

  • 控制序列化器的执行(检验、保存、转换数据)
  • 控制数据库查询的执行

先来看看这其中的人情世故:两个视图基本类,五个扩展类,九个视图子类,视图集方法,视图集··

视图组件大纲

两个视图基本类

导入

from rest_framework.views import APIView
from rest_framework.generics import GenericAPIView
  • APIView:DRF最顶层视图类
  • GenericAPIView:DRF通用视图类

五个扩展类

扩展类不是视图类,没有集成APIView,需要配合GenericAPIView使用,因为五个扩展类的实现需要调用GenericAPIView提供的序列化器与数据库查询的方法

主要是用来对数据进行增删改查

导入

from rest_framework.mixins import CreateModelMixin,ListModelMixin,DestroyModelMixin,RetrieveModelMixin,UpdateModelMixin
  • CreateModelMixin
  • ListModelMixin
  • DestroyModelMixin
  • RetrieveModelMixin
  • UpdateModelMixin

九个子类视图

导入

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

视图子类其实可以理解为GenericAPIView通用视图类和Mixin扩展类的排列组合组成的,底层事通过封装和继承来写

  • CreateAPIView

    提供 post 方法
    继承自: GenericAPIView、CreateModelMixin
  • ListAPIView

    提供 get 方法
    继承自:GenericAPIView、ListModelMixin
  • DestroyAPIView

    提供 delete 方法
    继承自:GenericAPIView、DestoryModelMixin
  • RetrieveAPIView

    提供 get 方法
    继承自: GenericAPIView、RetrieveModelMixin
  • UpdateAPIView

    提供 put 和 patch 方法
    继承自:GenericAPIView、UpdateModelMixin
  • ListCreateAPIView

    提供get 和 post方法
    继承自:ListModelMixin、CreateModelMixin、GenericAPIView
  • RetrieveUpdateAPIView

    提供 get、put、patch方法
    继承自: GenericAPIView、RetrieveModelMixin、UpdateModelMixin
  • RetrieveDestroyAPIView

    提供:get、delete方法
    继承自:RetrieveModelMixin、DestroyModelMixin、GenericAPIView
  • RetrieveUpdateDestroyAPIView

    提供 get、put、patch、delete方法
    继承自:GenericAPIView、RetrieveModelMixin、UpdateModelMixin、DestoryModelMixin

视图集

导入

from rest_framework.viewsets import ModelViewSet,ReadOnlyModelViewSet,ViewSet,GenericViewSet,ViewSetMixin

常用视图集父类

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

  • ReadOnlyModelViewSet:继承自GenericViewSet,同时包括了ListModelMixin、RetrieveModelMixin。

  • ViewSet:继承自APIView与ViewSetMixin,作用也与APIView基本类似,提供了身份认证、权限校验、流量管理等。ViewSet主要通过继承ViewSetMixin来实现在调用as_view()时传入字典({'get':'list'})的映射处理工作。

    • 在ViewSet中,没有提供任何动作action方法,需要我们自己实现action方法。
  • GenericViewSet:使用ViewSet通常并不方便,因为list、retrieve、create、update、destory等方法都需要自己编写,而这些方法与前面讲过的Mixin扩展类提供的方法同名,所以我们可以通过继承Mixin扩展类来复用这些方法而无需自己编写。但是Mixin扩展类依赖与GenericAPIView,所以还需要继承GenericAPIView。

    • GenericViewSet就帮助我们完成了这样的继承工作,继承自GenericAPIView与ViewSetMixin,在实现了调用as_view()时传入字典(如{'get':'list'}`)的映射处理工作的同时,还提供了GenericAPIView提供的基础方法,可以直接搭配Mixin扩展类使用。

魔法类

  • ViewSetMixin:控制自动生成路由

一览表

DRF中视图的“七十二变”

第一层是继承APIView写,第二层基于基于GenericAPIView写,第三层基于GenericAPIView+五个扩展类写,第四层通过九个视图子类来写,第五层是通过ViewSet写

ps:第几层是我意淫出来的词不要介意~,一层更比一层牛,欲练此功必先自宫!!!

第一层:基于APIview的五个接口

class BookView(APIView):
def get(self, requets):
# 序列化
book_list = models.Book.objects.all()
# 序列化多条数据many=True
ser = serializer.BookSerializer(instance=book_list, many=True)
return Response(ser.data) def post(self, request):
# 获取反序列化数据
ser = serializer.BookSerializer(data=request.data)
if ser.is_valid():
# 校验通过存入数据库,不需要重写create方法了
ser.save()
return Response({'code': 100, 'msg': '新增成功', 'data': ser.data})
# 校验失败
return Response({'code': 101, 'msg': '校验未通过', 'error': ser.errors}) class BookViewDetail(APIView):
def get(self, request, pk):
book = models.Book.objects.filter(pk=pk).first()
ser = serializer.BookSerializer(instance=book)
return Response(ser.data) def put(self, request, pk):
book = models.Book.objects.filter(pk=pk).first()
# 修改,instance和data都要传
ser = serializer.BookSerializer(instance=book, data=request.data)
if ser.is_valid():
# 校验通过修改,不需要重写update
ser.save()
return Response({'code:': 100, 'msg': '修改成功', 'data': ser.data})
# 校验不通过
return Response({'code:': 102, 'msg': '校验未通过,修改失败', 'error': ser.errors}) def delete(self, request, pk):
models.Book.objects.filter(pk=pk).delete()
return Response({'code': 100, 'msg': '删除成功'})

第一层五个接口demo

ModelSerializer序列化器实战 - HammerZe - 博客园 (cnblogs.com)

第二层:基于GenericAPIView的五个接口

常用类属性:

-GenericAPIView   继承了APIView,封装了一些属性和方法,跟数据库打交道
-queryset = None # 指定序列化集
-serializer_class = None # 指定序列化类
-lookup_field = 'pk' # 查询单条,分组分出来的参数,转换器对象参数的名字
-filter_backends # 过滤排序功能会用它
-pagination_class # 分页功能 -get_queryset() # 获取要序列化的数据,后期可能会重写
-get_object() # 通过lookup_field查询的
-get_serializer() # 使用它序列化
-get_serializer_class() # 返回序列化类 ,后期可能重写 demo:
# 指定序列化集
queryset = models.Book.objects.all()
# 指定序列化类
serializer_class = serializer.BookSerializer

第二层五个接口demo

from rest_framework.response import Response

from app01 import models
from app01 import serializer
from rest_framework.generics import GenericAPIView
# 书视图类
class BookView(GenericAPIView):
# 指定序列化集
queryset = models.Book.objects.all()
# 指定序列化类
serializer_class = serializer.BookSerializer
def get(self, requets):
# obj = self.queryset()
obj = self.get_queryset() # 等同于上面
# 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 = serializer.BookSerializer(data=request.data)
ser = self.get_serializer(data = request.data)
if ser.is_valid():
# 校验通过存入数据库,不需要重写create方法了
ser.save()
return Response({'code': 100, 'msg': '新增成功', 'data': ser.data})
# 校验失败
return Response({'code': 101, 'msg': '校验未通过', 'error': ser.errors}) class BookViewDetail(GenericAPIView):
# 指定序列化集
queryset = models.Book.objects.all()
# 指定序列化类
serializer_class = serializer.BookSerializer
def get(self, request, pk):
# book = models.Book.objects.filter(pk=pk).first()
book = self.get_object() # 根据pk拿到单个对象
# ser = serializer.BookSerializer(instance=book)
ser = self.get_serializer(instance=book)
return Response(ser.data) def put(self, request, pk):
# book = models.Book.objects.filter(pk=pk).first()
book = self.get_object()
# 修改,instance和data都要传
# ser = serializer.BookSerializer(instance=book, data=request.data)
ser = self.get_serializer(instance=book,data=request.data)
if ser.is_valid():
# 校验通过修改,不需要重写update
ser.save()
return Response({'code:': 100, 'msg': '修改成功', 'data': ser.data})
# 校验不通过
return Response({'code:': 102, 'msg': '校验未通过,修改失败', 'error': ser.errors}) def delete(self, request, pk):
# models.Book.objects.filter(pk=pk).delete()
self.get_object().delete()
return Response({'code': 100, 'msg': '删除成功'})

路由

path('books/', views.BookView.as_view()),
path('books/<int:pk>', views.BookViewDetail.as_view())

总结:到第二层只需修改querysetserializer_class类属性即可,其余都不需要修改

注意:虽然pk没有在orm语句中过滤使用,但是路由分组要用,所以不能删,或者写成*args **kwargs接收多余的参数,且路由转换器必须写成pk

# 源码
lookup_field = 'pk'
lookup_url_kwarg = None

get_queryset()方法可以重写,如果我们需要在一个视图类内操作另外表模型,来指定序列化的数据

class BookViewDetail(GenericAPIView):
queryset = models.Book.objects.all()
···
'''
指定序列化数据的格式:
self.queryset()
self.get_queryset() # 等同于上面
queryset = models.Book.objects.all()
'''
# 可以重写get_queryset方法在book视图类里操作作者模型
def get_queryset(self,request):
if self.request.path == '/user'
return Author.objects.all()
···
# 这样序列化的数据就不一样了,根据不同的条件序列化不同的数据 '''当然还可以通过重写get_serializer_class来返回其他序列化器类'''

第三层:基于GenericAPIView+五个视图扩展类写

五个视图扩展类:from rest_framework.mixins import CreateModelMixin,ListModelMixin,DestroyModelMixin,RetrieveModelMixin,UpdateModelMixin

通过GenericAPIView+视图扩展类来使得代码更简单,一个接口对应一个扩展类,注意扩展类不是视图类

  • ListModelMixin:获取所有API,对应list()方法
  • CreateModelMixin:新增一条API,对应create()方法
  • UpdateModelMixin:修改一条API,对应update()方法
  • RetrieveModelMixin:获取一条API,对应retrieve()方法
  • DestroyModelMixin:删除一条API,对应destroy()方法

注意:CreateModelMixin扩展类提供了更高级的方法,可以通过重写来校验数据存入

    def perform_create(self, serializer):
serializer.save()

第三层五个接口demo

from app01 import models
from app01 import serializer
from rest_framework.generics import GenericAPIView
from rest_framework.mixins import CreateModelMixin,ListModelMixin,DestroyModelMixin,RetrieveModelMixin,UpdateModelMixin # 获取所有和新增API
class BookView(ListModelMixin,CreateModelMixin,GenericAPIView):
queryset = models.Book.objects.all()
serializer_class = serializer.BookSerializer
def get(self, request):
return super().list(request) def post(self, request):
return super().create(request) # 获取删除修改单个API
class BookViewDetail(UpdateModelMixin,RetrieveModelMixin,DestroyModelMixin,GenericAPIView):
queryset = models.Book.objects.all()
serializer_class = serializer.BookSerializer
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)

总结

通过进一次封装+继承代码也变得越来越少了

GenericAPIView速写五个接口demo

模型

from django.db import models

# Create your models here.

# build four model tables

class Book(models.Model):
name = models.CharField(max_length=32)
price = models.DecimalField(decimal_places=2, max_digits=5)
publish = models.ForeignKey(to='Publish', on_delete=models.CASCADE)
authors = models.ManyToManyField(to='Author')
def __str__(self):
return self.name # 自定制字段
@property
def publish_detail(self):
return {'name': self.publish.name, 'addr': self.publish.city} @property
def author_list(self):
l = []
print(self.authors.all()) # <QuerySet [<Author: Author object (1)>, <Author: Author object (2)>]> for author in self.authors.all():
print(author.author_detail) # AuthorDetail object (1)
l.append({'name': author.name, 'age': author.age, 'addr': author.author_detail.addr})
return l class Author(models.Model):
name = models.CharField(max_length=32)
age = models.IntegerField()
author_detail = models.OneToOneField(to='AuthorDetail', on_delete=models.CASCADE) def __str__(self):
return self.name @property
def authordetail_info(self):
return {'phone':self.author_detail.telephone,'addr':self.author_detail.addr} class AuthorDetail(models.Model):
telephone = models.BigIntegerField()
addr = models.CharField(max_length=64) class Publish(models.Model):
name = models.CharField(max_length=32)
city = models.CharField(max_length=32)
email = models.EmailField()

序列化器

from django.db import models

# Create your models here.

# build four model tables

class Book(models.Model):
name = models.CharField(max_length=32)
price = models.DecimalField(decimal_places=2, max_digits=5)
publish = models.ForeignKey(to='Publish', on_delete=models.CASCADE)
authors = models.ManyToManyField(to='Author')
def __str__(self):
return self.name # 自定制字段
@property
def publish_detail(self):
return {'name': self.publish.name, 'addr': self.publish.city} @property
def author_list(self):
l = []
print(self.authors.all()) # <QuerySet [<Author: Author object (1)>, <Author: Author object (2)>]> for author in self.authors.all():
print(author.author_detail) # AuthorDetail object (1)
l.append({'name': author.name, 'age': author.age, 'addr': author.author_detail.addr})
return l class Author(models.Model):
name = models.CharField(max_length=32)
age = models.IntegerField()
author_detail = models.OneToOneField(to='AuthorDetail', on_delete=models.CASCADE) def __str__(self):
return self.name @property
def authordetail_info(self):
return {'phone':self.author_detail.telephone,'addr':self.author_detail.addr} class AuthorDetail(models.Model):
telephone = models.BigIntegerField()
addr = models.CharField(max_length=64) class Publish(models.Model):
name = models.CharField(max_length=32)
city = models.CharField(max_length=32)
email = models.EmailField()

视图

from rest_framework.generics import GenericAPIView
from rest_framework.mixins import ListModelMixin, CreateModelMixin, DestroyModelMixin, RetrieveModelMixin, \
UpdateModelMixin from app01 import models
from app01 import serializer # 书视图类
class BookView(ListModelMixin, CreateModelMixin, GenericAPIView):
queryset = models.Book.objects.all()
serializer_class = serializer.BookSerializer def get(self, request):
return super().list(request) def post(self, request):
return super().create(request) class BookViewDetail(RetrieveModelMixin, DestroyModelMixin, UpdateModelMixin, GenericAPIView):
queryset = models.Book.objects.all()
serializer_class = serializer.BookSerializer 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) # 作者
class AuthorView(ListModelMixin, CreateModelMixin, GenericAPIView):
queryset = models.Author.objects.all()
serializer_class = serializer.AuthorSerializer def get(self, request):
return super().list(request) def post(self, request):
return super().create(request) class AuthorViewDetail(RetrieveModelMixin, DestroyModelMixin, UpdateModelMixin, GenericAPIView):
queryset = models.Author.objects.all()
serializer_class = serializer.AuthorSerializer 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) # 作者详情 class AuthorDetailView(ListModelMixin, CreateModelMixin, GenericAPIView):
queryset = models.AuthorDetail.objects.all()
serializer_class = serializer.AuthorDetailSerializer def get(self, request):
return super().list(request) def post(self, request):
return super().create(request) class OneAuthorViewDetail(RetrieveModelMixin, DestroyModelMixin, UpdateModelMixin, GenericAPIView):
queryset = models.AuthorDetail.objects.all()
serializer_class = serializer.AuthorDetailSerializer 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) # 出版社
class PublishView(ListModelMixin, CreateModelMixin, GenericAPIView):
queryset = models.Publish.objects.all()
serializer_class = serializer.PublishSerializer def get(self, request):
return super().list(request) def post(self, request):
return super().create(request) class PublishViewDetail(RetrieveModelMixin, DestroyModelMixin, UpdateModelMixin, GenericAPIView):
queryset = models.Publish.objects.all()
serializer_class = serializer.PublishSerializer 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)

路由

from django.contrib import admin
from django.urls import path from app01 import views urlpatterns = [
path('admin/', admin.site.urls),
# 书
path('books/', views.BookView.as_view()),
path('books/<int:pk>', views.BookViewDetail.as_view()), # 作者
path('authors/', views.AuthorView.as_view()),
path('authors/<int:pk>', views.AuthorViewDetail.as_view()), # 作者详情
path('authorsdetail/', views.AuthorDetailView.as_view()),
path('authorsdetail/<int:pk>', views.OneAuthorViewDetail.as_view()), # 出版社
path('publish/', views.PublishView.as_view()),
path('publish/<int:pk>', views.PublishViewDetail.as_view()),
]

Postman以及测完,请放心使用~

第四层:GenericAPIView+九个视图子类写五个接口

导入视图子类from rest_framework.generics import CreateAPIView,ListAPIView,DestroyAPIView,RetrieveAPIView,UpdateAPIView,ListCreateAPIView,RetrieveUpdateAPIView,RetrieveUpdateDestroyAPIView,RetrieveDestroyAPIView

使用哪个继承哪个就可以了,具体可以看继承的父类里有什么方法不需要刻意去记

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

# 1、查询所有,新增API
class BookView(ListCreateAPIView):
queryset = models.Book.objects.all()
serializer_class = serializer.BookSerializer
# 2、新增接口
class BookView(CreateAPIView):
queryset = models.Book.objects.all()
serializer_class = serializer.BookSerializer
# 3、查询接口
class BookView(ListAPIView):
queryset = models.Book.objects.all()
serializer_class = serializer.BookSerializer # 4、查询单个,修改一个,删除一个接口
class BookViewDetail(RetrieveUpdateDestroyAPIView):
queryset = models.Book.objects.all()
serializer_class = serializer.BookSerializer # 5、查询单个接口
class BookViewDetail(RetrieveAPIView):
queryset = models.Book.objects.all()
serializer_class = serializer.BookSerializer # 6、修改单个接口
class BookViewDetail(UpdateAPIView):
queryset = models.Book.objects.all()
serializer_class = serializer.BookSerializer # 7、删除单个接口
class BookViewDetail(DestroyAPIView):
queryset = models.Book.objects.all()
serializer_class = serializer.BookSerializer # 8、查询单个、修改接口
class BookViewDetail(RetrieveUpdateAPIView):
queryset = models.Book.objects.all()
serializer_class = serializer.BookSerializer # 9、查询单个、删除接口
class BookViewDetail(RetrieveDestroyAPIView):
queryset = models.Book.objects.all()
serializer_class = serializer.BookSerializer '''上述共九个视图子类,九九归一剑诀~''' # 更新和删除接口自己整合
class BookViewDetail(UpdateAPIView,DestroyAPIView):
queryset = models.Book.objects.all()
serializer_class = serializer.BookSerializer

第四层快速写五个接口demo

from rest_framework.generics import ListCreateAPIView, RetrieveUpdateDestroyAPIView

from app01 import models
from app01 import serializer class BookView(ListCreateAPIView):
queryset = models.Book.objects.all()
serializer_class = serializer.BookSerializer class BookViewDetail(RetrieveUpdateDestroyAPIView):
queryset = models.Book.objects.all()
serializer_class = serializer.BookSerializer
'''其余的和第三层一样'''

第五层:基于ViewSet写五个接口

视图集导入from rest_framework.viewsets import ModelViewSet,ReadOnlyModelViewSet,ViewSet,GenericViewSet,ViewSetMixin

路由导入from rest_framework.routers import SimpleRouter,DefaultRouter

基于ViewSet视图集写,需要我们配置路由

  • 方法一

    from django.urls import path, include
    from rest_framework.routers import SimpleRouter
    from app01 import views router = SimpleRouter()
    router.register('books', views.BookView, 'books')
    urlpatterns = [
    ...
    ]
    urlpatterns += router.urls
    '''
    register(self, prefix, viewset, basename=None)
    prefix:路由url前缀
    viewset:处理请求的viewset类
    basename:路由名称的前缀,一般和prefix写成一样就行
    '''
    # 等同于
    path('books/'),include(router.urls)
    path('books/<int:pk>'),include(router.urls)
  • 方法二

    router = SimpleRouter()
    router.register('books', views.BookView, 'books') urlpatterns = [
    ...
    url(r'^', include(router.urls))
    ] # 生成两种路由
    path('/api/v1'),include(router.urls)
    # [<URLPattern '^books/$' [name='books-list']>, <URLPattern '^books/(?P<pk>[^/.]+)/$' [name='books-detail']>]
    # 等同于自己配的
    path('/api/v1/books/'),include(router.urls)
    path('/api/v1/books/<int:pk>'),include(router.urls)

    异同

    • 同:方法一和方法二都可以自动生成路由,代替了下面的路由

      path('books/', views.BookView.as_view()),
      path('books/<int:pk>', views.BookViewDetail.as_view()),
    • 异:方法二可以拼接路径,如果不拼接是和方法一一样的

两种不同的路由

第五层基于ModelViewSet视图集写五个接口demo

views.py

from rest_framework.viewsets import ModelViewSet,ReadOnlyModelViewSet,ViewSet,GenericViewSet,ViewSetMixin
class BookView(ModelViewSet):
queryset = models.Book.objects.all()
serializer_class = serializer.BookSerializer

urls.py

from django.contrib import admin
from django.urls import path, include
from rest_framework.routers import SimpleRouter from app01 import views router = SimpleRouter()
router.register('books', views.BookView, 'books') urlpatterns = [
path('admin/', admin.site.urls),
path('api/v1/',include(router.urls)),
]

ps:剩下的都一样~

ReadOnlyModelViewSet视图集

继承该ReadOnlyModelViewSet视图集的作用是只读,只做查询,修改删除等操作不允许

from rest_framework.viewsets import ModelViewSet,ReadOnlyModelViewSet,ViewSet,GenericViewSet,ViewSetMixin
class BookView(ReadOnlyModelViewSet):
queryset = models.Book.objects.all()
serializer_class = serializer.BookSerializer

两个视图集总结

  • ModelViewSet可以写五个接口,而ReadOnlyModelViewSet只能写两个接口

本质

  • ModelViewSet继承了五个视图扩展类+GenericViewSet,GenericViewSet继承了ViewSetMixin+GenericAPIView

    PS:ViewSetMixin控制了路由写法

  • ReadOnlyModelViewSet继承了RetrieveModelMixin+ListModelMixin+GenericViewSet

其他视图集

ViewSet

ViewSet = ViewSetMixin+APIView


class ViewSet(ViewSetMixin, views.APIView):
"""
The base ViewSet class does not provide any actions by default.
"""
pass

GenericViewSet

GenericViewSet = ViewSetMixin+GenericAPIView

class GenericViewSet(ViewSetMixin, generics.GenericAPIView):
"""
The GenericViewSet class does not provide any actions by default,
but does include the base set of generic view behavior, such as
the `get_object` and `get_queryset` methods.
"""
pass

ViewSetMixin

魔术视图类,控制自动生成路由,可以通过组合继承,以前的写法可以继续使用,但是如果要自动生成路由必须得继承ViewSetMixin及其子类;或者选择继承ViewSet、GenericViewSet

class ViewSetMixin:
"""
This is the magic. Overrides `.as_view()` so that it takes an `actions` keyword that performs
the binding of HTTP methods to actions on the Resource. For example, to create a concrete view binding the 'GET' and 'POST' methods
to the 'list' and 'create' actions... view = MyViewSet.as_view({'get': 'list', 'post': 'create'})
"""
这就是魔法。 重写' .as_view() ',以便它接受一个' actions '关键字执行
将HTTP方法绑定到资源上的动作。 例如,创建绑定'GET'和'POST'方法的具体视图
到“列表”和“创建”动作… = MyViewSet视图。 As_view ({'get': 'list', 'post': 'create'})

总结

  • 第一层:基于APIView写视图,get、post、put、delete都需要自己写,序列化的数据和序列化类需要获取后指定

    class BookView(APIView):
    def get(self, requets):
    book_list = models.Book.objects.all()
    ser = serializer.BookSerializer(instance=book_list, many=True)
    return Response(ser.data)
  • 第二层:基于GenericAPIView写视图,优化了视图类内序列化数据和序列化类的代码冗余问题,通过querysetserializer_class指定序列化集和序列化器即可,一个视图类内写一次即可,最后通过get_querysetget_serializer方法处理

    class BookView(GenericAPIView):
    queryset = models.Book.objects.all()
    serializer_class = serializer.BookSerializer
    def get(self, requets):
    obj = self.get_queryset()
    ser = self.get_serializer(instance=obj,many=True)
    return Response(ser.data)
  • 第三层:基于GenericAPIView+5个视图扩展类写视图,每个扩展类对应一个接口,更加细化,通过继承父类(扩展类)减少了代码的冗余

    class BookView(ListModelMixin,CreateModelMixin,GenericAPIView):
    queryset = models.Book.objects.all()
    serializer_class = serializer.BookSerializer
    def get(self, request):
    return super().list(request)
  • 第四层,基于九个视图子类写,视图子类将扩展类和GenericAPIView封装到一块,使得我们要写的代码更少了,总之就是牛逼~

    class BookView(ListCreateAPIView):
    queryset = models.Book.objects.all()
    serializer_class = serializer.BookSerializer
  • 第五层,基于ViewSet写视图,这样以来5个接口就都在一个视图类内,代码更少了,但是可扩展性低了,路由也是问题,get所有和get一条路由冲突需要修改

    class BookView(ModelViewSet):
    queryset = models.Book.objects.all()
    serializer_class = serializer.BookSerializer
    '''路由'''
    router = SimpleRouter()
    router.register('books', views.BookView, 'books') urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/v1/',include(router.urls)),
    ]



累死,有错误请指正~感谢

DRF 视图组件的更多相关文章

  1. DRF视图组件

    DRF视图组件: CVB模式继承----五层 from django.views import View # Django的View from rest_framework.views import ...

  2. drf视图组件、认证组件

    视图组件 1.基本视图 url(r'^publish/$', views.PublishView.as_view()), url(r'^publish/(?P<pk>\d+)/$', vi ...

  3. DRF 视图组件,路由组件

    视图组件  -- 第一次封装   -- GenericAPIView(APIView):    queryset = None    serializer_class = None    def ge ...

  4. DRF 视图组件代码

    序列化器代码 # 声明序列化器from rest_framework import serializersfrom djangoDome.models import Book class Publis ...

  5. DRF之视图组件

    不断的优化我们写的程序,是每个程序员必备的技能和职业素养,也是帮助我们成长的非常重要的手段. 使用serializer进行put接口设计 根据规范,PUT接口用来定义用户对数据修改的逻辑,也就是upd ...

  6. 【DRF框架】视图组件

    基于mixins视图类 from rest_framework import mixins # 创建视图 class CreateModelMixin(object) def create(self, ...

  7. DRF的视图组件

    目录 DRF的视图组件 两大视图类 六大视图工具类 九大工具视图类 两大视图集基类 DRF的视图组件 DRF的视图组件大概分以下几类 两大视图类 APIView.GenericAPIView from ...

  8. DRF - 序列化组件(GET/PUT/DELETE接口设计)、视图优化组件

    一.序列化组件 基于上篇随笔的表结构 , 通过序列化组件的ModelSerializer设计如下三个接口 : GET 127.0.0.1:8000/books/{id} # 获取一条数据,返回值:{} ...

  9. DRF Django REST framework 之 视图组件(四)

    引言 在我们有几十上百的视图类,都有get,post等方法,在功能类似时,会导致大量的重复代码出现,显然还有很多可以优化的地方.这也就有了视图组件,它的功能非常强大,能很好的优化接口逻辑. 视图组件 ...

随机推荐

  1. (第二章第二部分)TensorFlow框架之读取图片数据

    系列博客链接: (第二章第一部分)TensorFlow框架之文件读取流程:https://www.cnblogs.com/kongweisi/p/11050302.html 本文概述: 目标 说明图片 ...

  2. App测试如何进行?手机app测试要点

    手机APP测试,主要针对的是android和ios两大主流操作系统,主要考虑的就是功能性.兼容性.稳定性.易用性(也就是人机交互).性能. 手机APP测试前的准备: 1.使用同类型的产品,不仅仅是使用 ...

  3. python+selenium+pycharm使用

    上一章节讲了安装python及selenium,该章节讲解下使用pycharm编辑器进行代码编写 下载地址:http://www.jetbrains.com/pycharm/download/#sec ...

  4. 接口自动化测试框架(Java 实现)

    目录 需求分析 开发设计 分层与抽象 技术选型 主要类设计 测试文件设计 工程目录设计 工程实现 github 地址 运行示例 需求分析 需求点 需求分析 通过 yaml 配置接口操作和用例 后续新增 ...

  5. CMAK(Kafka Manager)安装

    CMAK 是管理Kafka集群的常用工具,之前的名字叫Kafka Manager.CMAK功能很强大,它可以管理多个Kafka集群,查看集群内部状态,如:topic.broker.consumer.p ...

  6. laravel7 数据迁移及填充数据

    1:置迁移数据表,创建生成模型和迁移文件: php artisan make:model Article -m 2:接着,在框架中的database/migrations文件夹中找到刚创建的用户表Ar ...

  7. 微信小程序防抖

    https://www.cnblogs.com/daviddd/p/12470480.html 1:wxml:设置一个按钮 <button type="primary" bi ...

  8. freeswitch tts_commandline模块介绍

    概述 freeswitch是开源.免费的VOIP软交换平台,自带了很多功能各异的模块. mod_tts_commandline模块,本身没有TTS能力,而是通过调用TTS引擎的命令生成语音文件,tts ...

  9. 【基础】工作中常用的linux命令,经常会被面试官问到

    前言 面试经常会问到一些Linux操作命令,下面就工作中常用的和面试问的频率较高的命令做详细描述. 常用命令 修改密码:passwd 用户名 切换用户名:su 用户名 查看当前路径:pwd 调整路径: ...

  10. Golang 基础之基础语法梳理 (二)

    大家好,今天将梳理出的 Go语言基础语法内容,分享给大家. 请多多指教,谢谢. 本次<Go语言基础语法内容>共分为三个章节,本文为第二章节 Golang 基础之基础语法梳理 (一) Gol ...