DRF视图

DRF视图

1. Reqest 与 Response

1.1 Request

REST framework 传入视图的request对象是REST framework提供的扩展了HttpRequest类的Request类的对象。提供了Parser解析器,在接收到请求后会自动根据Content-Type指明的请求数据类型(如JSON、表单等)将请求数据进行parse解析,解析为类字典对象保存到Request对象中

request.data 返回解析之后的请求体数据
request.query_paramsDjango标准的request.GET作用相同

1.2 Response

REST framework提供了一个响应类Response,使用该类构造响应对象时,响应的具体数据内容会被转换(render渲染)成符合前端需求的类型。

构造方式 Response(data, status=None, template_name=None, headers=None, content_type=None)

常用属性:

  • .data:传给response对象的序列化后,但尚未render处理的数据

  • .status_code:状态码的数字

  • .content:经过render处理后的响应数据

2. 视图

2.1 APIView

rest_framework.views.APIView
APIViewREST framework提供的所有视图的基类

APIView中仍以常规的类视图定义方法来实现get()post() 或者其他请求方式的方法。

###
urlpatterns = [
    url("^books/$", views.IdcList.as_view(), name="book-list"),
    url("^books/(?P<pk>[0-9]+)/$", views.IdcDetail.as_view(), name="book_detail")
]
###
from rest_framework.views import APIView
from rest_framework.response import Response
from django.http import Http404

class BookList(APIView):
    def get(self, request, format=None):
        queryset = Book.objects.all()
        serializer = BookSerializer(queryset, many=True)
        return Response(serializer.data)

    def post(self, request, format=None):
        serializer = BookSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.data, status=status.HTTP_400_BAD_REQUEST)



class BookDetail(APIView):
    # 该方法自定义
    def get_object(self, pk):
        try:
            return Book.objects.get(pk=pk)
        except Idc.DoesNotExist:
            raise Http404

    def get(self, request, pk, format=None):
        Book = self.get_object(pk)
        serializer = BookSerializer(Book)
        return Response(serializer.data)

    def put(self, request, pk, format=None):
        Book = self.get_object(pk)
        serializer = BookSerializer(idc, data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        return Response(serializer.errors, status=status.HTTP_404_NOT_FOUND)

    def delete(self, request, pk, format=None):
        Book = self.get_object(pk)
        Book.delete()
        return HttpResponse(status=status.HTTP_204_NO_CONTENT)

2.2 GenericAPIView

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

提供的关于序列化器使用的属性与方法

属性:

  • serializer_class 指明视图使用的序列化器

方法:

  • get_serializer_class(self) 返回序列化器类

  • get_serializer(self, args, *kwargs) 返回序列化器对象

提供的关于数据库查询的属性与方法

属性:

  • queryset 指明使用的数据查询集

方法:

  • get_queryset(self) 返回视图使用的查询集
  • get_object(self) 返回视图所需的模型类数据对象
# url(r'^books/(?P<pk>\d+)/$', views.BookDetailView.as_view()),
class BookDetailView(GenericAPIView):
    queryset = BookInfo.objects.all()
    serializer_class = BookInfoSerializer

    def get(self, request, pk):
        book = self.get_object() # get_object()方法根据pk参数查找queryset中的数据对象
        serializer = self.get_serializer(book)
        return Response(serializer.data)

2.3 五个扩展类

提供了几种后端视图(对数据资源进行曾删改查)处理流程的实现,如果需要编写的视图属于这五种,则视图可以通过继承相应的扩展类来复用代码,减少自己编写的代码量。

这五个扩展类需要搭配GenericAPIView父类,因为五个扩展类的实现需要调用GenericAPIView提供的序列化器与数据库查询的方法

  • ListModelMixin
  • CreateModelMixin
  • RetrieveModelMixin
  • UpdateModelMixin
  • DestoryModelMixin
2.3.1 ListModelMixin

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

from rest_framework.mixins import ListModelMixin

class BookListView(ListModelMixin, GenericAPIView):
    queryset = BookInfo.objects.all()
    serializer_class = BookInfoSerializer

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

创建视图扩展类,提供create(request, *args, **kwargs)方法快速实现创建资源的视图,成功返回201状态码。

如果序列化器对前端发送的数据验证失败,返回400错误。

2.3.3 RetrieveModelMixin

创建视图扩展类,提供create(request, *args, **kwargs)方法快速实现创建资源的视图,成功返回201状态码。

如果序列化器对前端发送的数据验证失败,返回400错误。

class BookDetailView(RetrieveModelMixin, GenericAPIView):
    queryset = BookInfo.objects.all()
    serializer_class = BookInfoSerializer

    def get(self, request, pk):
        return self.retrieve(request)
2.3.4 UpdateModelMixin

更新视图扩展类,提供update(request, *args, **kwargs)方法,可以快速实现更新一个存在的数据对象。

同时也提供partial_update(request, *args, **kwargs)方法,可以实现局部更新。

成功返回200,序列化器校验数据失败时,返回400错误。

2.3.5 DestoryModelMixin

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

成功返回204,不存在返回404。

2.4 八个可用子类视图

2.4.1 CreateAPIView

提供 post 方法

继承自: GenericAPIViewCreateModelMixin

2.4.2 ListAPIView

提供 get 方法

继承自:GenericAPIViewListModelMixin

2.4.3 RetrieveAPIView

提供 get 方法

继承自: GenericAPIViewRetrieveModelMixin

2.4.4 DestoryAPIView

提供 delete 方法

继承自:GenericAPIViewDestoryModelMixin

2.4.5 UpdateAPIView

提供 put patch 方法

继承自:GenericAPIViewUpdateModelMixin

2.4.6 RetrieveUpdateAPIView

提供 getputpatch方法

继承自: GenericAPIViewRetrieveModelMixinUpdateModelMixin

2.4.7 RetrieveUpdateDestoryAPIView

提供 getputpatchdelete方法

继承自:GenericAPIViewRetrieveModelMixinUpdateModelMixinDestoryModelMixin

3. 视图集ViewSet

3.1 ViewASet

Django REST framework允许你将一组相关视图的逻辑组合在单个类(称为 ViewSet)中。 在其他框架中,你也可以找到概念上类似于 Resources Controllers的类似实现。

ViewSet 只是一种基于类的视图,它不提供任何方法处理程序(如 .get().post()),而是提供诸如 .list().create() 之类的操作。

通常不是在 urlconf 中的视图集中显示注册视图,而是要使用路由类注册视图集,该类会自动为你确定 urlconf

使用视图集ViewSet,可以将一系列逻辑相关的动作放到一个类中:

  • list() 提供一组数据
  • retrieve() 提供单个数据
  • create() 创建数据
  • update() 保存数据
  • destory() 删除数据

ViewSet视图集类不再实现get()post()等方法,而是实现动作 actionlist() create()

视图集只在使用as_view()方法的时候,才会将action动作与具体请求方式对应上。如:

# 定义一个简单的视图集,可以用来列出或检索系统中的所有用户。
from django.contrib.auth.models import User
from django.shortcuts import get_object_or_404
from myapps.serializers import UserSerializer
from rest_framework import viewsets
from rest_framework.response import Response

class UserViewSet(viewsets.ViewSet):
    """
    A simple ViewSet for listing or retrieving users.
    """
    def list(self, request):
        queryset = User.objects.all()
        serializer = UserSerializer(queryset, many=True)
        return Response(serializer.data)

    def retrieve(self, request, pk=None):
        queryset = User.objects.all()
        user = get_object_or_404(queryset, pk=pk)
        serializer = UserSerializer(user)
        return Response(serializer.data)

3.2 GenericViewSet

使用ViewSet通常并不方便,因为listretrievecreateupdatedestory等方法都需要自己编写,而这些方法与前面讲过的Mixin扩展类提供的方法同名,所以我们可以通过继承Mixin扩展类来复用这些方法而无需自己编写。但是Mixin扩展类依赖与GenericAPIView,所以还需要继承GenericAPIView

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

3.3 ModelViewSet

继承自GenericViewSet,同时包括了ListModelMixinRetrieveModelMixinCreateModelMixinUpdateModelMixinDestoryModelMixin

3.4 ReadOnlyModelViewSet

继承自GenericViewSet,同时包括了ListModelMixinRetrieveModelMixin

class AccountViewSet(viewsets.ReadOnlyModelViewSet):
    """
    A simple ViewSet for viewing accounts.
    """
    queryset = Account.objects.all()
    serializer_class = AccountSerializer

3.5 视图集中定义附加action动作

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

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

    def latest(self, request):
        """
        返回最新的图书信息
        """
        book = BookInfo.objects.latest('id')
        serializer = self.get_serializer(book)
        return Response(serializer.data)

    def read(self, request, pk):
        """
        修改图书的阅读量数据
        """
        book = self.get_object()
        book.bread = request.data.get('bread')
        book.save()
        serializer = self.get_serializer(book)
        return Response(serializer.data)```

--------------------------------------------------------
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'})),
]

3.6 路由Routers

对于视图集ViewSet,我们除了可以自己手动指明请求方式与动作action之间的对应关系外,还可以使用Routers来帮助我们快速实现路由信息。

# 创建router对象,并注册视图集,例如

from rest_framework import routers

router = routers.SimpleRouter()
router.register(r'books', BookInfoViewSet, base_name='book')

如上述代码会形成的路由如下:
^books/$    name: book-list
^books/{pk}/$   name: book-detail

-----------------------------------------------------

# 添加路由数据
urlpatterns = [
    ...
    url(r'^', include(router.urls))
]

在视图集中,如果想要让Router自动帮助我们为自定义的动作生成路由信息,需要使用rest_framework.decorators.action装饰器。

action装饰器装饰的方法名会作为action动作名,与listretrieve等同。

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

methods: 声明该action对应的请求方式,列表传递
detail: 声明该action的路径是否与单一资源对应,及是否是xxx//action方法名/
True 表示路径格式是xxx//action方法名/
False 表示路径格式是xxx/action方法名/

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 表示路径名格式应该为 books/latest/
    @action(methods=['get'], detail=False)
    def latest(self, request):
        """
        返回最新的图书信息
        """
        ...

    # detail为True,表示路径名格式应该为 books/{pk}/read/
    @action(methods=['put'], detail=True)
    def read(self, request, pk):
        """
        修改图书的阅读量数据
        """
        ...

---------------------------------------------------
# 由路由器自动为此视图集自定义action方法形成的路由会是如下内容:
^books/latest/$    name: book-latest
^books/{pk}/read/$  name: book-read

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Joyce Lee

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值