首页 > 其他分享 >DRF视图组件

DRF视图组件

时间:2023-02-03 22:25:21浏览次数:71  
标签:GenericAPIView ser get self 视图 组件 import DRF

DRF视图组件


 

文章目录

 

一、视图

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

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

视图继承关系

REST framework 提供了众多的通用视图基类与扩展类,以简化视图的编写。

img

二、2个视图基类

1.APIView

from rest_framework.views import APIView

APIView与View

  • APIView是REST framework 提供的所有视图的基类, 继承自Django的View父类

  • APIView 相比较与 View, 它对Django原生的 request 对象进行了处理转成了 DRF 的 request对象

  • 并重写了 dispatch 方法, 在路由分发之前会对请求进行身份认证, 权限检查, 频率控制

  • 重写了View中通过本次请求的方式动态的反射到自定义继承APIView类实例化的对象中定义的请求方法

  • 设置全局异常处理

  • 处理完毕异常以后使用的是 drf 的 response 对象对请求响应

示例(基于APIView写接口)

  • APIView中仍以常规的类视图定义方法来实现get( ) 、post( ) 或者其他请求方式的方法
  • 导入方式 : from rest_framework.views import APIView
  • models.py
from django.db import models

# Create your models here.
class Book(models.Model):
    name = models.CharField(max_length=32)
    price = models.CharField(max_length=32)

    publish = models.ForeignKey(to='Publish',on_delete=models.CASCADE)
    authors = models.ManyToManyField(to='Author')

    def publish_detail(self):
        return {'publish':self.publish.name,'addr':self.publish.addr}

    def author_list(self):
        l = []
        for author in self.authors.all():
            l.append({'name':author.name,'phone':author.phone})
            return l



class Publish(models.Model):
    name = models.CharField(max_length=32)
    addr = models.CharField(max_length=32)


class Author(models.Model):
    name = models.CharField(max_length=32)
    phone = models.CharField(max_length=11)
  • serializers.py
from rest_framework import serializers
from .models import Book

class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = Book
        fields = ['name','price','publish','authors','publish_detail','author_list']
       
        extra_kwargs = {'name':{'max_length':8},
                        'publish':{'write_only':True},
                        'authors':{'write_only':True},
                        'publish_detail': {'read_only': True},
                        'author_list': {'read_only': True}
                        }    
  • views.py
from rest_framework.views import APIView
from .models import Book,Publish,Author
from rest_framework.response import Response
from .serializer import BookSerializer

# Create your views here.
class BookView(APIView):
    # 查询所有
    def get(self,request):
        books = Book.objects.all()
        ser = BookSerializer(instance=books,many=True)
        print(ser.data)
        return Response(ser.data)

    #新增一条
    def post(self,request):
        ser = BookSerializer(data=request.data)
        if ser.is_valid():
            ser.save()
            return Response({'code':'100','msg':'新增成功','result':ser.data})
        else:
            return Response({'code':101,'msg':ser.errors})


class BookDetail(APIView):
    # 查询一条
    def get(self,request,pk):
        book = Book.objects.filter(pk=pk).first()
        ser = BookSerializer(instance=book)
        print(ser.data)
        return Response(ser.data)

    #修改一条
    def put(self,request,pk):
        book = Book.objects.filter(pk=pk).first()
        ser = BookSerializer(data=request.data,instance=book)
        if ser.is_valid():
            ser.save()
            return Response({'code': 100, 'msg': '修改成功','result':ser.data})
        else:
            return Response({'code': 101, 'msg': ser.errors})
    
    # 删除一条
    def delete(self,request,pk):
        Book.objects.filter(pk=pk).delete()
        return Response({'code':100,'msg':'删除成功'})
  • urls.py
urlpatterns = [
    path('admin/', admin.site.urls),
    path('books/', views.BookView.as_view()),
    path('books/<int:pk>/', views.BookDetail.as_view()),
]

小结

  1. 继承关系:APIView继承View

  2. APIView基于View的拓展:

    APIView重写了View的dispatch方法,在该方法中实现了以下一些功能:

    1. 对来的原生请求对象request进行了封装.

    2. 提供了对包装过后的请求对象的三段认证:认证,权限控制、频率控制

    3. 重写了View中通过本次请求的方式动态的反射到自定义继承APIView类实例化的对象中定义的请求方法

    4. 使用异常处理处理2,3步骤中的异常

    5. 处理完毕异常以后使用drf的Response对象响应请求

  3. 针对路由配置:

    • 路由中的有名分组必须指定pk, 视图中使用必须使用相同的关键字参数接受

2.GenericAPIView (通用视图类)

1. GenericAPIView介绍

  • 继承自APIVIew, 主要增加了操作序列化器数据库查询的方法, 作用是为下面Mixin扩展类的执行提供方法支持; 通常在使用时, 可搭配一个或多个Mixin扩展类
  • 导入方式 : from rest_framework.generics import GenericAPIView

2.提供关于序列化器的属性和方法

  • 属性
属性作用
queryset (常用) 需要序列化的查询集
serializer_class (常用) 指定使用的序列化器
pagination_class 分页控制类
filter_backends 过滤控制后端
lookup_field 查询单一数据库对象时使用的条件字段,默认为**’pk’**
  • 方法
方法作用
get_queryset( ) (常用) 获取QuerySet查询集
get_object( ) (常用) 获取一条数据对象
get_serializer( ) 返回序列化器对象,可以其他视图或扩展类使用
get_serializer_class 返回序列化器类,默认返回serializer_class,可以重写

3.示例(基于GenericAPIView 写接口)

  • models.py 文件不变
  • serializers.py 文件不变
  • urls.py不变
  • views.py
from .models import Book,Publish,Author
from rest_framework.response import Response
from .serializer import BookSerializer
from rest_framework.generics import GenericAPIView

class BookView(GenericAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

    def get(self, request):
        # objs = self.queryset #这里可以拿到,但是不要这么用,GenericAPIView提供了一个方法(.get_queryset())
        objs = self.get_queryset()  # 好处,可以重写该方法,后期可扩展性高
        # 取序列化类,不要使用self.serializer_class,而要使用方法(.get_serializer())
        ser = self.get_serializer(instance=objs, many=True)  # 后期可以重写get_serializer_class,指定使用哪个序列化类来序列化
        return Response(ser.data)

    def post(self, request):
        ser = self.get_serializer(data=request.data)
        if ser.is_valid():
            ser.save()
            # 咱们现在只有ser序列化类的对象,但是咱们想要,新增的对象---》序列化成字典---》大前提,序列化类中的create方法一定要返回新增的对象
            return Response({'code': 100, 'msg': '新增成功', 'result': ser.data})
        else:
            return Response({'code': 101, 'msg': ser.errors})


class BookDetailView(GenericAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

    def get(self, request, pk):
        obj = self.get_object()  # 获取单条
        ser = self.get_serializer(instance=obj)
        return Response(ser.data)

    def put(self, request, pk):
        obj = self.get_object()
        ser = self.get_serializer(instance=obj, data=request.data)
        if ser.is_valid():
            ser.save()
            return Response({'code': 100, 'msg': '修改成功', 'result': ser.data})
        else:
            return Response({'code': 101, 'msg': ser.errors})

    def delete(self, request, pk):
        self.get_object().delete()
        return Response({'code': 100, 'msg': '删除成功'})

查询条件使用的条件字段是有 lookup_field 属性来控制的, 默认是 pk, 可以修改

三、基于GenericAPIView+5个视图扩展类写接口

1.五个视图扩展类

扩展类提供方法用途
ListModelMixin list() 获得多条数据对象
CreateModelMixin create() 新建单一数据对象
RetrieveModelMixin retrieve() 获得单一数据对象
UpdateModelMixin update() 更新一条数据
DestroyModelMixin destroy() 删除单⼀一对象

2.作用

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

3.示例

  • models.py 文件不变
  • serializers.py 文件不变
  • urls.py不变
  • views.py
from .models import Book,Publish,Author
from .serializer import BookSerializer
from rest_framework.generics import GenericAPIView
from rest_framework.mixins import ListModelMixin,CreateModelMixin,RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin

class BookView(GenericAPIView, ListModelMixin, CreateModelMixin):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

    def get(self, request):
        return self.list(request)

    def post(self, request):
        return self.create(request)


class BookDetailView(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

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

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

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

四、9个视图子类

1.九个视图子类

子类提供方法继承自
CreateAPIView 提供 post 方法 GenericAPIView、CreateModelMixin
ListAPIView 提供 get 方法 GenericAPIView、ListModelMixin
RetireveAPIView 提供 get 方法 GenericAPIView、RetrieveModelMixin
DestoryAPIView 提供 delete 方法 GenericAPIView、DestoryModelMixin
UpdateAPIView 提供 put 和 patch 方法 GenericAPIView、UpdateModelMixin
ListCreateAPIView 提供 get、post方法 GenericAPIView、ListModelMixin、CreateModelMixin
RetrieveUpdateAPIView 提供 get、put、patch方法 GenericAPIView、RetrieveModelMixin、UpdateModelMixin
RetrieveDestroyAPIView 提供 get、put、patch方法 GenericAPIView、RetrieveModelMixin、DestoryModelMixin
RetrieveUpdateDestoryAPIView 提供 get、put、patch、delete方法 GenericAPIView、RetrieveModelMixin、UpdateModelMixin、DestoryModelMixin

2.示例

  • models.py 文件不变
  • serializers.py 文件不变
  • views.py
from rest_framework.generics import CreateAPIView      # 新增
from rest_framework.generics import ListAPIView        # 查看所有
from rest_framework.generics import ListCreateAPIView  # 查看所有新增一个
from rest_framework.generics import RetrieveAPIView    # 查看一个
from rest_framework.generics import DestroyAPIView     # 删除一个
from rest_framework.generics import UpdateAPIView      # 修改一个
from rest_framework.generics import RetrieveUpdateAPIView  # 查看一个,修改一个
from rest_framework.generics import RetrieveDestroyAPIView  # 查看一个,删除一个
from rest_framework.generics import RetrieveUpdateDestroyAPIView  # 查看一个,修改一个,删除一个
  • urls.py
path('publish3/', views.PublishView3.as_view()),
path('publish3/<int:pk>',views.PublishDeUpReView2.as_view()),
 

五、视图集(ViewSet)

1.为什么要有视图集?

  • 不同的视图集继承了不同的视图基类、视图子类或者视图扩展类, 我们使用视图集可以更加方便的操作数据

  • 在没有视图集之前, DRF五大接口帮我们实现数据操作 : get_one, get_list, post, put, delete

  • 我们可以写一个类, 然后继承GenericAPIView的九个视图子类来实现五个接口

  • 但是出现的问题是 : 查询所有使用 get 方法, 查询一条也是使用 get 方法, 但是在Python中, 同一个类中不能有相同的方法名

  • 于是DRF的作者在这个类中不再实现get( )、post( )等方法, 而是将它们映射成对应的 action 行为

  • 查询所有的 get( ) 方法映射成 list( ), 查询一条的 get( ) 方法映射成 retrive( ), 这就是视图集的由来

2.视图集的作用

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

3.常用的视图集父类

ViewSet

  • 继承自:APIViewViewSetMixin

  • 作用 : 与APIView基本类似,提供了身份认证、权限校验、流量管理等

  • ViewSet主要通过继承ViewSetMixin来实现在调用as_view( )时传入字典的映射处理工作

  • 缺点 : 在ViewSet中,没有提供任何动作action方法,需要我们自己实现action方法

GenericViewSet

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

ModelViewSet

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

ReadOnlyModelViewSet

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

4.示例

  • views.py
from rest_framework.viewsets import ModelViewSet  # 继承GenericViewSet + 五个接口都有
from rest_framework.viewsets import ReadOnlyModelViewSet  # 继承GenericViewSet + 只有读两个接口
from rest_framework.viewsets import GenericViewSet  # 继承GenericAPIView与ViewSetMixin
from rest_framework.viewsets import ViewSet  # 继承的APIView与ViewSetMixin
from rest_framework.viewsets import ViewSetMixin  # 提供修改路由中ac_view()类方法的actions参数


class PublishView4(ModelViewSet):
    queryset = models.Publish.objects.all()
    serializer_class = PublishSerializer
  • urls.py
# 需要书写方法映射关系
path('publish4/', views.PublishView4.as_view(actions={'get':'list','post':'create'})),
path('publish4/<int:pk>', views.PublishView4.as_view(actions={'get':'retrieve','put':'update','delete':'destroy'})),
  • 视图集在使用as_view() 方法的时候需要书写方法与action的映射关系, 因为ViewSetMixin重写了父类的as_view()方法, 在书写路由的时候就需要以上面的方式书写
  • 在继承ViewSetMixin的时候一定要将其放在最左边, 这样在调用as_view()方法的时候才会先调用ViewSetMixin中的as_view()方法
  • 上面的四种常用视图集都直接或间接的继承了ViewSetMixin

5.视图集中定义附加的action动作

在视图集中,除了上述默认的方法动作外,还可以添加自定义动作

  • views.py
class PublishView5(GenericViewSet):
    queryset = models.Publish.objects.all()
    serializer_class = PublishSerializer
    # 自定义的 action
    def get_xxx(self,request):
        query_set = self.get_queryset()
        serializer = self.get_serializer(query_set,many=True)
        return Response(serializer.data)
  • urls.py
path('publish5/', views.PublishView5.as_view(actions={'get': 'get_xxx'})),

6.action 属性

在视图集中,我们可以通过action对象属性来获取当前请求视图集时的action动作是哪个

class PublishView5(GenericViewSet):
    queryset = models.Publish.objects.all()
    serializer_class = PublishSerializer
    # 自定义的 action
    def get_xxx(self,request):
        query_set = self.get_queryset()
        serializer = self.get_serializer(query_set,many=True)
        print(self.action)  # get_xxx
        return Response(serializer.data)

六.DRF视图关系继承图

ps : 在 Pycharm 中可以鼠标右击一个视图类------>Diagrams------>Show Diagrams 来查看这个类的继承关系

image-20210415183341863

  • 视图提供的相应方法图

DRF视图关系图

标签:GenericAPIView,ser,get,self,视图,组件,import,DRF
From: https://www.cnblogs.com/chen-ao666/p/17090336.html

相关文章

  • 视图组件介绍及两个视图基类
    1.反序列化类校验码部分源码解析(了解)#反序列化校验,什么时候,开始执行校验 -视图类中的ser.is_valid(),就会执行校验,校验通过返回True,不通过返回False#入口:ser.is_va......
  • 反序列化类校验部分源码解析,断言,drf之请求与响应
    反序列化类校验部分源码解析反序列化校验,什么时候开始执行校验(切入点)视图类中的ser.is_valid(),就会执行校验,校验通过返回True,不通过返回False入口:ser.is_valid()......
  • drf-请求/相应/视图组件/
    内容概要反序列化类校验部分源码解析断言drf-请求drf-响应视图组件介绍及两个视图基类基于GenericAPIView+5个视图扩展类反序列化类校验部分源码分析......
  • drf从入门到精通 05
    今日内容详细1.反序列化类校验部分源码解析#反序列化校验什么时候开始执行校验 -视图类中的ser.is_valid()就会开始执行校验校验通过返回True不通过返回False......
  • django框架之drf(部分讲解)
    一、反序列化类校验部分源码解析(了解即可)反序列化校验,什么时候,开始执行校验?视图类中的ser.is_valid(),就会执行校验,校验通过返回True,不通过返回False源码入口#......
  • drf-day5——反序列化类校验部分源码分析、断言、drf请求、drf响应、视图组件及两个视
    目录一、反序列化类校验部分源码解析(了解)二、断言三、drf之请求3.1Request能够解析的前端传入的编码格式3.2Request类有哪些属性和方法(学过)常用参数Response类的实例化......
  • drf之路由Routers
    #2.路由Routers对于视图集ViewSet,我们除了可以自己手动指明请求方式与动作action之间的对应关系外,还可以使用Routers来帮助我们快速实现路由信息。如果是非视图集,不需......
  • Django框架之drf:5、反序列化器校验部分源码分析、断言、drf之请求与响应、视图组件介
    Django框架之drf目录Django框架之drf一、反序列化类校验部分源码解析二、断言三、drf之请求1、Request能够解析的前端传入编码格式2、Request类中的属性和方法四、drf之......
  • drf之视图集ViewSet
    ##1.3视图集ViewSet使用视图集ViewSet,可以将一系列视图相关的代码逻辑和相关的http请求动作封装到一个类中:-list()提供一组数据-retrieve()提供单个数据-crea......
  • drf视图组件与视图基类
    drf视图组件视图就是视图类,我们之前学过的APIView就是drf提供的基类。APIView与原生View区别: 1.传入到视图类中的是drf的Request对象而不是django的request对象 2.视图......