rest_framework(6)GenericAPIView

本系列文章中的上一篇文章:ModelSerializer 的使用

GenericAPIView 的好处

"""
使用 GenericAPIView 的好处:
    分析之前的 BookView 类,无论是 get、post或是其他请求,都只涉及两个变量:
        即模型集合(或对象)和序列化器实例对象
    然后对 Book 模型类进行增删改查的逻辑处理
    加入现在有其他的模型类,如 Author、Publish 等,也是要对它们进行增删改查操作
    这些表的处理逻辑都是非常相似的,如果用 APIView ,也可以实现,但是会有很多重复的逻辑(即增删改查)
    而使用 GenericAPIView 类,就可以将这些重复的逻辑进行代码重构,实现代码复用

    比如现在写的是对 BookView 类进行增删改查,而当要对另一个表进行增删改查时,
    get、post 方法的代码都不需要改变,只需要改变雷属性 queryset 和 serializer_class 的值
"""

views.py 代码

from rest_framework.generics import GenericAPIView
from rest_framework import serializers
from rest_framework.response import Response
from sers.models import Book


class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = Book
        fields = "__all__"  # 针对所有的数据库字段进行序列化


"""
GenericAPIView 的源码(关键部分):
class GenericAPIView(views.APIView):
    queryset = None
    serializer_class = None

    # 返回 QuerySet 集合
    def get_queryset(self):
        # ...

        # self 此时指的是 BookView 类实例对象
        # 所以 self.queryset 指的是 BookView 类的雷属性 queryset = Book.objects.all()
        # queryset 的值为一个 QuerySet 集合
        queryset = self.queryset
        if isinstance(queryset, QuerySet):
            queryset = queryset.all()

        # 返回查询集合,里面包含的都是从数据库中查找到的模型对象
        return queryset

    # 返回单个对象,如返回一本书的信息
    # 是在 QuerySet 集合中查找一个对象
    def get_object(self):
        queryset = self.filter_queryset(self.get_queryset())

        # lookup_field = 'pk' 也就是在 queryset 集合找查找一个对象的过滤条件
        # 需要在 URL 中定义一个名为 pk 的正则表达式的有名分组
        # 因为 lookup_field 的默认值是 pk ,如果没有改分组,将找不到对象
        # 本质就是 obj = queryset.filter(pk=pk)
        lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field
        
        # 一个断言...

        filter_kwargs = {self.lookup_field: self.kwargs[lookup_url_kwarg]}
        obj = get_object_or_404(queryset, **filter_kwargs)
        self.check_object_permissions(self.request, obj)

        return obj

    # 返回一个序列化器对象
    def get_serializer(self, *args, **kwargs):
        # 调用 self.get_serializer_class() 方法得到序列化器类名,即 BookSerializer (看以下解析)
        serializer_class = self.get_serializer_class()
        kwargs.setdefault('context', self.get_serializer_context())

        # 返回序列化器 BookSerializer 的实例对象
        # 根据传入的参数创建一个序列化器对象
        # 所以 get_serializer() 方法得到的是一个序列化器对象
        # 本案例中等价于 return BookSerializer(instance=self.get_queryset(), many=True)
        return serializer_class(*args, **kwargs)

    # 返回序列化器的类名
    def get_serializer_class(self):
        # 一个断言 ...

        # self 此时指的是 BookView 类实例对象
        # 所以 self.serializer_class 得到的是 BookView 类的类属性 serializer_class = BookSerializer
        # 所以返回的是 BookSerializer 这个序列化器类
        return self.serializer_class

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

    # 假设有一个 get 请求,查询所有书籍信息
    def get(self, request):
        # book_list = Book.objects.all()
        # _serializers = BookSerializer(instance=book_list, many=True)

        # book_list = self.get_queryset()
        # # self.get_serializer_class() 得到的是序列化器的类名,此处得到的是 BookSerializer
        # # 所以以下等价于 BookSerializer(instance=book_list, many=True)
        # self.get_serializer_class()(instance=book_list, many=True)

        # 另一种写法
        _serializers = self.get_serializer(instance=self.get_queryset(), many=True)

        return Response(_serializers.data)

    # 假设有一个 post 请求,添加一个书籍
    def post(self, request):
        # serializer = BookSerializer(data=request.date)
        serializer = self.get_serializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        else:
            Response(serializer.errors)

你可能感兴趣的:(开发语言,python,django,restful)