码迷,mamicode.com
首页 > 其他好文 > 详细

【DRF视图】

时间:2018-12-25 21:13:47      阅读:168      评论:0      收藏:0      [点我收藏+]

标签:gen   article   取数据   exist   err   size   update   不能   rom   

目录

请结合【DRF序列化】此文献中的数据文件及序列化文件来阅读如下代码.

DRF视图为我们提供了非常简便的方法——内置了增删改查等一系列的操作.
我们只需在url中指定对应的方法,视图继承内置方法的类,即可实现两三行代码搞定一个请求.

@
*
我们先看看仿照内置方法实现的**

APIView视图文件:

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.viewsets import ViewSetMixin



""" ===================== 一层封装 ===================== """


class GenericAPIView(APIView):
    queryset = None
    serializer_class = None

    def get_queryset(self):
        """用于获取queryset的方法"""
        return self.queryset.all()

    def get_serializer(self, *args, **kwargs):
        """用于调用序列化类的方法"""
        return self.serializer_class(*args, **kwargs)


class ListModelMixin():
    """用于返回get请求所有数据的数据"""
    def list(self, request):
        queryset = self.get_queryset()  # self调用的方法(get_queryset)是从执行此方法(list)的当前对象的类中开始找
        ser_obj = self.get_serializer(queryset, many=True)  # 原理同上句话
        return Response(ser_obj.data)


class CreateModelMixin():
    """用于处理post请求发来的数据"""
    def create(self, request):
        ser_obj = self.get_serializer(data=request.data)
        if ser_obj.is_valid():
            ser_obj.save()
            return Response(ser_obj.validated_data)
        return Response(ser_obj.errors)


class RetrieveModelMixin():
    """用于返回get请求查询单条数据方法"""
    def retrieve(self, request, id):
        book_obj = self.get_queryset().filter(id=id).first()
        ser_obj = self.get_serializer(book_obj)
        return Response(ser_obj.data)


class UpdateModelMixin():
    """用于处理put请求发来的数据(更新数据)"""
    def update(self, request, id):
        book_obj = self.get_queryset().filter(id=id).first()
        ser_obj = self.get_serializer(instance=book_obj, data=request.data, partial=True)
        if ser_obj.is_valid():
            ser_obj.save()
            return Response(ser_obj.validated_data)
        return Response(ser_obj.errors)


class DestroyModelMixin():
    """用于删除单条数据"""
    def destroy(self, request, id):
        book_obj = self.get_queryset().filter(id=id).first()
        if book_obj:
            book_obj.delete()
            return Response(‘‘)
        return Response(‘The deleted object does not exist.‘)



""" ===================== 二层封装 ===================== """


class ListCreateAPIView(GenericAPIView, ListModelMixin, CreateModelMixin):
    pass


class RetrieveUpdateDestroyAPIView(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin):
    pass

视图文件:

from .custom_mixin import ListCreateAPIView, RetrieveUpdateDestroyAPIView  # 导入上述的APIView视图文件
from DRFView import models
from .serializers import BookSerializer  # 导入自定义的序列化文件


class Book(ListCreateAPIView):
    queryset = models.Book.objects.all()  # 坑:这里的queryset只是放到缓存里了,再次取时还需要用.all()方法
    serializer_class = BookSerializer

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

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


class BookEdit(RetrieveUpdateDestroyAPIView):
    queryset = models.Book.objects.all()
    serializer_class = BookSerializer

    def get(self, request, id):
        return self.retrieve(request, id)

    def put(self, request, id):
        return self.update(request, id)

    def delete(self, request, id):
        return self.destroy(request, id)

改进版

urls.py文件:

urlpatterns = [
    url(r‘^book/$‘, BookModel.as_view({‘get‘: ‘list‘, ‘post‘: ‘create‘})),
    url(r‘^book/(?P<id>\d+)/$‘, BookModelView.as_view({‘get‘: ‘retrieve‘, ‘put‘: ‘update‘, ‘delete‘: ‘destroy‘})),
]
"""
注意as_view的传参:
as_view({"请求方式": "调用的方法"}, {...})
指定请求方式调用的方法后,框架会为我们自动执行其方法,无需在CBV中写请求的方法了.
"""

APIView视图文件:

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.viewsets import ViewSetMixin  # 导入DRF封装好的APIView


""" ===================== 第一层封装 ===================== """


class GenericAPIView(APIView):
    queryset = None
    serializer_class = None

    def get_queryset(self):
        """用于获取queryset的方法"""
        return self.queryset.all()

    def get_serializer(self, *args, **kwargs):
        """用于调用序列化类的方法"""
        return self.serializer_class(*args, **kwargs)


class ListModelMixin():
    """用于返回get请求所有数据的数据"""
    def list(self, request):
        queryset = self.get_queryset()  # self调用的方法(get_queryset)是从执行此方法(list)的当前对象的类中开始找
        ser_obj = self.get_serializer(queryset, many=True)  # 原理同上句话
        return Response(ser_obj.data)


class CreateModelMixin():
    """用于处理post请求发来的数据"""
    def create(self, request):
        ser_obj = self.get_serializer(data=request.data)
        if ser_obj.is_valid():
            ser_obj.save()
            return Response(ser_obj.validated_data)
        return Response(ser_obj.errors)


class RetrieveModelMixin():
    """用于返回get请求查询单条数据方法"""
    def retrieve(self, request, id):
        book_obj = self.get_queryset().filter(id=id).first()
        ser_obj = self.get_serializer(book_obj)
        return Response(ser_obj.data)


class UpdateModelMixin():
    """用于处理put请求发来的数据(更新数据)"""
    def update(self, request, id):
        book_obj = self.get_queryset().filter(id=id).first()
        ser_obj = self.get_serializer(instance=book_obj, data=request.data, partial=True)
        if ser_obj.is_valid():
            ser_obj.save()
            return Response(ser_obj.validated_data)
        return Response(ser_obj.errors)


class DestroyModelMixin():
    """用于删除单条数据"""
    def destroy(self, request, id):
        book_obj = self.get_queryset().filter(id=id).first()
        if book_obj:
            book_obj.delete()
            return Response(‘‘)
        return Response(‘The deleted object does not exist.‘)



""" ===================== 第二层封装 ===================== """


class ListCreateAPIView(GenericAPIView, ListModelMixin, CreateModelMixin):
    pass


class RetrieveUpdateDestroyAPIView(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin):
    pass



""" ===================== 第三层封装 ===================== """


class ModelViewSet(ViewSetMixin, ListCreateAPIView, RetrieveUpdateDestroyAPIView):
# ViewSetMixin重写了as_view方法,即可以传参了.
    pass

视图文件:

from .custom_mixin import ModelViewSet  # 导入上述的APIView视图文件
from DRFView import models
from .serializers import BookSerializer  # 导入自定义的序列化文件


class BookModel(ModelViewSet):
    queryset = models.Book.objects.all()  
    # 坑:这里的queryset只是放到缓存里了,再次取时还需要用.all()方法
    # queryset是框架能识别的,会把数据放到缓存中,如果该成其它的名字则不会缓存(比如query),即再此取数据时不能加.all()
    serializer_class = BookSerializer


class BookModelView(ModelViewSet):
    queryset = models.Book.objects.all()
    serializer_class = BookSerializer

接下来,我们再来看看DRF为我们封装好了的APIView用法。
***

开始使用内置视图

第一步 按照框架的要求写url

urlpatterns = [
    url(r‘^book/$‘, BookModel.as_view({‘get‘: ‘list‘, ‘post‘: ‘create‘})),
    # 按照APIView的要求,这里必须写为pk,而不能写id
    url(r‘^book/(?P<pk>\d+)/$‘, BookModelView.as_view({‘get‘: ‘retrieve‘, ‘put‘: ‘update‘, ‘delete‘: ‘destroy‘})),
]
"""
注意as_view的传参:
as_view({"请求方式": "调用的方法"}, {...})
指定请求方式调用的方法后,无需在CBV中写请求的方法了.
"""

第二步 写视图文件
```python
from DRFView import models
from .serializers import BookSerializer # 导入自定义的序列化文件
from rest_framework.viewsets import ModelViewSet # 导入DRF封装好的APIView

class BookModel(ModelViewSet):
queryset = models.Book.objects.all()
serializer_class = BookSerializer

class BookModelView(ModelViewSet):
queryset = models.Book.objects.all()
serializer_class = BookSerializer

如上步骤,我们的视图只要写两行就可以了.

关于DRF视图源码解析,推荐参考此文献:https://www.cnblogs.com/GGGG-XXXX/articles/9675911.html

继承顺序图解:
技术分享图片

【DRF视图】

标签:gen   article   取数据   exist   err   size   update   不能   rom   

原文地址:https://www.cnblogs.com/zyk01/p/10176367.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!