欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

DRF框架-View视图

程序员文章站 2022-07-12 11:18:07
...

View视图使用

推荐官网:https://www.django-rest-framework.org/api-guide/views/

APIView(一级视图)

集成于Django的view类,和view不同地方在于:

传递给处理程序方法的请求将是REST框架的Request实例,而不是Django的HttpRequest实例。
处理程序方法可能返回REST框架的Response,而不是Django的HttpResponse…视图将管理内容协商和在响应上设置正确的呈现器。
任何APIException例外情况将被捕获并调解成适当的反应。
传入的请求将进行身份验证,并在将请求发送给处理程序方法之前,将运行适当的权限和/或节流检查。

点击查看类内容:

class APIView(View):

    # The following policies may be set at either globally, or per-view.
    renderer_classes = api_settings.DEFAULT_RENDERER_CLASSES
    parser_classes = api_settings.DEFAULT_PARSER_CLASSES
    # 身份认证
    authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES
    throttle_classes = api_settings.DEFAULT_THROTTLE_CLASSES
    permission_classes = api_settings.DEFAULT_PERMISSION_CLASSES
    content_negotiation_class = api_settings.DEFAULT_CONTENT_NEGOTIATION_CLASS
    metadata_class = api_settings.DEFAULT_METADATA_CLASS
    versioning_class = api_settings.DEFAULT_VERSIONING_CLASS

写一个get和post请求实例:

from rest_framework.response import Response
from rest_framework.viewsets import ModelViewSet
from rest_framework.views import APIView
from rest_framework import authentication, permissions
from goods.serializers import *

class ListGoodsView(APIView):
	# 可以不需要验证
    # authentication_classes = (authentication.TokenAuthentication, )
    # permission_classes = (permissions.IsAdminUser, )

    def get(self, request, format=None):
        goods = [good.name for good in GoodsInfo.objects.all()]
        # 多条数据要写many=True
        data = GoodsInfo.objects.all()
        ser = GoodsInfoNewSerializer(data, many=True)
        return Response(ser.data)

    def post(self, request):
    	# 反序列化需要data=
        ser = GoodsInfoNewSerializer(data=request.data)
        # 需要验证
        ser.is_valid()
        print(ser.validated_data)
        ser.save()
        return Response(ser.validated_data)

GenericAPIView(二级视图)和mixins

这个是对APIView的再次封装,实现更强和更简洁的功能,通常还会和mixins联合使用:

GenericAPIView的属性

加入queryset属性,可以直接设置这个属性,不必再将实例化的courses,再次传给seriliazer,系统会自动检测到。除此之外,可以重载get_queryset(),这样就不必设置’queryset=*’,这样就变得更加灵活,可以进行完全的自定义。
加入serializer_class属性与实现get_serializer_class()方法。两者的存在一个即可,通过这个,在返回时,不必去指定某个serilizer
lookup_field-模型字段,用于对单个模型实例执行对象查找。默认为’pk’…注意,在使用超链接API时,需要确保双管齐下API视图和如果需要使用自定义值,序列化程序类将设置查找字段
设置过滤器模板:filter_backends
设置分页模板:pagination_class

mixins类

1.ListModelMixin

列表视图扩展类,提供list(request, *args, **kwargs)方法快速实现列表视图,返回200状态码。
该Mixin的list方法会对数据进行过滤和分页。

2.CreateModelMixin

创建视图扩展类,提供create(request, *args, **kwargs)方法快速实现创建资源的视图,成功返回201状态码。
如果序列化器对前端发送的数据验证失败,返回400错误。

3.RetrieveModelMixin

详情视图扩展类,提供retrieve(request, *args, **kwargs)方法,可以快速实现返回一个存在的数据对象。
如果存在,返回200, 否则返回404。

4.UpdateModelMixin

更新视图扩展类,提供update(request, *args, **kwargs)方法,可以快速实现更新一个存在的数据对象。
同时也提供partial_update(request, *args, **kwargs)方法,可以实现局部更新。
成功返回200,序列化器校验数据失败时,返回400错误。

5.DestroyModelMixin

删除视图扩展类,提供destroy(request, *args, **kwargs)方法,可以快速实现删除一个存在的数据对象。
成功返回204,不存在返回404。

混合使用实例:

mixins的子类中会带有对应可以使用的方法,看上文,这时候要写queryset和serializer_class以及对应的请求方式,并返回mixins子类中的方法

from goods.serializers import *
from rest_framework.mixins import *
from rest_framework.generics import *
class GenericsView(GenericAPIView, ListModelMixin):
    queryset = GoodsInfo.objects.all()
    serializer_class = GoodsInfoNewSerializer

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

如果直接使用下文的子类更简单:
意思是自动调用post方法,不需要再自己调用这个方法

from goods.serializers import *
from rest_framework.generics import *
class CreateGoodsView(CreateAPIView):
    # queryset = GoodsInfo.objects.all() # 创建的时候可以不用设置数据库内容
    serializer_class = GoodsInfoNewSerializer

三级视图(XXAPIView)

使用已有的子类代表GenericAPIView和mixins的混合使用
几个子类视图

1.CreateAPIView

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

2.ListAPIView

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

3.RetireveAPIView

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

4.DestoryAPIView

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

5.UpdateAPIView

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

6.RetrieveUpdateAPIView

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

7.RetrieveUpdateDestoryAPIView

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

ViewSet的使用

视图集ViewSet,使用视图集ViewSet,可以将一系列逻辑相关的动作放到一个类中。使用ViewSet时不需要再views.py里写get->return list这种类型的,只需要在urls.py里写对应逻辑:
views.py内容:自己导包

class MyViewSet(GenericViewSet, ListModelMixin):
    queryset = GoodsInfo.objects.filter(id__gt=15)
    serializer_class = GoodsInfoNewSerializer
class GoodsInfoView(ModelViewSet):
    # 先导包ModelViewSet和数据库Model和serializers下的类
    # queryset是一个查询集,存储所有的数据库查询之后的数据,是一个属性不能修改名字
    queryset = GoodsInfo.objects.all()
    '''serializer_class用来指定再当前的视图立面进行序列化和反序列化时
    使用的序列化器(也叫串行器)'''
    serializer_class = GoodsInfoNewSerializer

urls.py内容,两种方式,router是自动完成绑定:

from django.conf.urls import url, include
from goods.views import *
from rest_framework.routers import DefaultRouter

# 定义视图处理的路由器
router = DefaultRouter()
# 在路由器中注册视图集

router.register('showgoods', GoodsInfoView, base_name='hello')
router.register('viewset', MyViewSet, base_name='viewset')

urlpatterns = [
    url(r'', include(router.urls)),
    url(r'^goodslist/$', ListGoodsView.as_view()),
    url(r'^show/$', GenericsView.as_view()),
    url(r'^(?P<pk>\d+)+(/showgoods/)$', GoodsInfoView.as_view({'get':'retrieve','post':'create','put':'update'})),
]

或者这样写:

viewset = MyViewSet.as_view({
    'get': 'list',
    })
    # 商品列表页
url('viewset/', goods_list,name="viewset"),

1. ViewSet

继承自APIView,作用也与APIView基本类似,提供了身份认证、权限校验、流量管理等。

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

2.GenericViewSet

继承自GenericAPIView,作用也与GenericAPIVIew类似,提供了get_object、get_queryset等方法便于列表视图与详情信息视图的开发。

3.ModelViewSet

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

4.ReadOnlyModelViewSet

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

ViewSet添加自定义动作
添加自定义动作需要使用rest_framework.decorators.action装饰器。

以action装饰器装饰的方法名会作为action动作名,与list、retrieve等同。

action装饰器可以接收两个参数:

methods: 该action支持的请求方式,列表传递
detail: 表示是action中要处理的是否是视图资源的对象(即是否通过url路径获取主键)
True 表示使用通过URL获取的主键对应的数据对象
False 表示不使用URL获取主键
实例:

from rest_framework import mixins
from rest_framework.viewsets import GenericViewSet
from rest_framework.decorators import action
 
class BookInfoViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, GenericViewSet):
    queryset = BookInfo.objects.all()
    serializer_class = BookInfoSerializer
 
    # detail为False 表示不需要处理具体的BookInfo对象
    @action(methods=['get'], detail=False)
    def latest(self, request):
        """
        返回最新的图书信息
        """
        book = BookInfo.objects.latest('id')
        serializer = self.get_serializer(book)
        return Response(serializer.data)
 
    # detail为True,表示要处理具体与pk主键对应的BookInfo对象
    @action(methods=['put'], detail=True)
    def read(self, request, pk):
        """
        修改图书的阅读量数据
        """
        book = self.get_object()
        book.bread = request.data.get('read')
        book.save()
        serializer = self.get_serializer(book)
        return Response(serializer.data)

urls.py的跳转逻辑:

urlpatterns = [
    url(r'^books/$', views.BookInfoViewSet.as_view({'get': 'list'})),
    url(r'^books/latest/$', views.BookInfoViewSet.as_view({'get': 'latest'})),
    url(r'^books/(?P<pk>\d+)/$', views.BookInfoViewSet.as_view({'get': 'retrieve'})),
    url(r'^books/(?P<pk>\d+)/read/$', views.BookInfoViewSet.as_view({'put': 'read'})),
]