DRF框架的视图简析

首先我们明确REST接口开发的核心任务

在开发REST API接口时,视图中做的最主要有三件事:

  • 将请求的数据(如JSON格式)转换为模型类对象
  • 操作数据库
  • 将模型类对象转换为响应的数据(如JSON格式)

一:使用Django开发REST 接口

数据的获取和返回格式的组织,都要开发人员自己编写。返回对象为HttpResponseJsonResponse等一些子类对象,视图类继承自View   

class BooksView(View):
    """
    查询所有图书
    """
    def get(self, request):
        """
        查询所有图书
        路由:GET /books/
        """
        queryset = BookInfo.objects.all()
        book_list = []
        for book in queryset:
            book_list.append({
                'id': book.id,
                'btitle': book.btitle,
                'bpub_date': book.bpub_date,
                'bread': book.bread,
                'bcomment': book.bcomment,
                'image': book.image.url if book.image else ''
            })
        return JsonResponse(book_list, safe=False)

附:响应对象要带上状态码201(新建、修改), 204(删除), 查询不用加status 会自动返回200(成功)、404(失败)

二:使用Django REST framework(DRF)框架来开发REST接口

想对于Django开发此接口 来看看DRF框架做的逐步封装简化

1.序列化器的引入对数据对象进行转换的操作不再需要开发人员去完成,且包含了对数据的验证功能。

class BooksView(View):
    """查询所有图书信息
    """
    def get(self, request):
        """
        查询所有图书
        路由:GET /books/
        """
        books = BookInfo.objects.all()
        book_serializer = BookInfoSerializer(books, many=True)
        book_dict = book_serializer.data
        print(book_dict)
        return JsonResponse(book_dict, safe=False)

2.视图类的封装拓展:

2.1)两个API视图基类(继承自Django的View类) [代码体现在Response的简便]

"""DRF框架的APIView类、GenericAPIView类,和django中View主要的不同就是请求对象和响应对象不同"""

request:

request.data返回解析之后的请求体数据

request.query_params与Django标准的request.GET相同,获取查询字符串。

Response:

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

Response(data, status=None, template_name=None, headers=None, content_type=None)

继承自APIView的视图代码:

class BooksAPIView(APIView):
    """查询所有图书信息
    """
    def get(self, request):
        """
        查询所有图书
        路由:GET /books/
        """
        books = BookInfo.objects.all()
        book_serializer = BookInfoSerializer(books, many=True)
        book_dict = book_serializer.data
        print(book_dict)
        return Response(book_dict)  # safe=False不需要写了

2.2) GenericAPIView类 继承自APIView,主要增加了操作序列化器和数据库查询的方法 [代码体现在数据的操作和方法的简便],一般和5个Mixin拓展类配合使用,为他们提供方法支持。5个扩展类:List、Create、Retrieve、Update、DestroyModelMixin (前面几个省略一点 :))

from rest_framework.mixins import ListModelMixin
from rest_framework.generics import GenericAPIView

class BooksListView(ListModelMixin, GenericAPIView):
    """只用指明数据模型类queryset
       序列化器serializer_class
       数据的操作也简化了,不在需要开发人员去进行序列化器的操作了
    """
    queryset = BookInfo.objects.all()
    serializer_class = BookInfoSerializer

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

2.3) 继承自Mixin扩展类和GenericAPIView的子类可用视图 [代码体现在方法都不用写了],CreateAPIView、ListAPIView、Retrieve、Update、Destroy、

RetrieveUpdate、RetrieveUpdateDestrop  (后面省略了APIView  :))

from rest_framework.generics import ListAPIView
# ListAPIView 继承自GenericAPIView, ListModelMixin
class BooksListAPIView(ListAPIView):  # 可使用ListCreateAPIView
    """此时的视图只用指定两个属性,方法都不用写了
       但是带pk和不带pk的还是要分两个视图类编写
    """
    queryset = HeroInfo.objects.all()
    serializer_class = HeroInfoSerializer

2.4) 视图集ViewSet,使用视图集,可以将一系列相关的逻辑都放到一个类里面了 [代码主要体现在只用写一个视图类],不需要再使用两个视图类来放不同的逻辑代码。但是设置路由比较特别

视图代码:

from rest_framework import mixins
from rest_framework.viewsets import GenericViewSet
from rest_framework.decorators import action

class BooksViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin,..., GenericViewSet):
    """查询多个、查询单个、新增、修改的逻辑都在视图集里面所包含"""
    queryset = BookInfo.objects.all()
    serializer_class = BookInfoSerializer

路由设置:

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

2.5) 终极简便视图集ModelViewSet [代码体现在继承类不用写那么多了,但路由的配置也比较特别],继承自GenericViewSet,同时包括了ListModelMixin、RetrieveModelMixin......

视图代码:

from rest_framework.viewsets import ModelViewSet

class BooksModelViewSet(ModelViewSet):
    queryset = HeroInfo.objects.all()
    serializer_class = HeroInfoSerializer

 路由:Routrs

from rest_framework import routers

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

urlpatterns = [
    ...
]
urlpatterns += router.urls

 register(prefix, viewset, base_name)

  • prefix 该视图集的路由前缀
  • viewset 视图集
  • base_name 路由名称的前缀

猜你喜欢

转载自blog.csdn.net/Best_fish/article/details/83268538