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. Python推导式

    Python推导式 推导式:是Python中提供的一个非常方便的功能,可以通过一行代码实现创建 list.dict.tuple.set的同时初始化一些值. 1.列表推到式 # -*- coding: ...

  2. python中的流程控制

    目录 引言 流程控制的分类 分支结构 单if结构 if与else结构 if与elif与else结构 if分支的嵌套 循环结构 while循环 while + break循环 while + conti ...

  3. Jquery.Validate清除验证信息|laydate时间控件无法清除validate提示问题

    最近做一个需求,用到模态框和Jquery.Validate验证框架: 点击添加时弹出模态框,当输入数据保存时如果数据不能通过校验,则会触发Validate验证并显示提示信息: 如果此时关闭弹出层,下次 ...

  4. windows下安装gym

    安装gym在执行pip install -e'.[all]'这句语句时,可能会出现这种情况 在pycharm中运行的时候会出现如下这种情况: 或者这种情况 出现这种问题可能是python的版本太高了, ...

  5. git合并分支代码的方法

    1.先提交本地代码,防止被拉取其他分支的代码污染(self为自己的分支 other为想要拉取的分支) git add . git commit -m '备注信息' git push origin se ...

  6. 制作CocoaPods公有库和私有库

    认识公有库和私有库 公有库:开源自己封装的库供别人使用,且往cocoaPods的官方Repo仓库(即CocoaPods Master Repo)中新增自己库的索引,该库索引是以*.podspec.js ...

  7. LGP3281口胡

    当你看到一个东西的时候,GF 有可能比 DP 更方便.处理贡献也有可能比 DP 更方便. 这个题意明显是让我们计算 \(S(r)-S(l-1)\) 之类的东西( 所以直接考虑前缀的答案就好了( 考虑将 ...

  8. 《Shader入门精要》中MVP变换的Projection矩阵与《GAMES101图形学入门》中的区别

    game101的透视投影的投影矩阵是这样的 正交投影是这样的 而shader入门精要的透视投影矩阵是这样子 正交投影矩阵是这样子 game101的透视投影是这样得到的 而正交投影的时候并没有假设中心点 ...

  9. 用 EXISTS 或 NOT EXISTS 用法

    项目中遇到这么个情况: t1表 和 t2表  都是150w条数据,600M的样子,都不算大. 但是这样一句查询 ↓ select * from t1 where phone not in (selec ...

  10. Linux企业常用命令详解

    cat :查看 cat [-AbeEnstTuv] [--help] [--version] fileName 常用参数: -n :由 1 开始对所有输出的行数编号 -b :和 -n 相似,对于空白行 ...