本系列文章中的上一篇文章:ModelSerializer 的使用
""" 使用 GenericAPIView 的好处: 分析之前的 BookView 类,无论是 get、post或是其他请求,都只涉及两个变量: 即模型集合(或对象)和序列化器实例对象 然后对 Book 模型类进行增删改查的逻辑处理 加入现在有其他的模型类,如 Author、Publish 等,也是要对它们进行增删改查操作 这些表的处理逻辑都是非常相似的,如果用 APIView ,也可以实现,但是会有很多重复的逻辑(即增删改查) 而使用 GenericAPIView 类,就可以将这些重复的逻辑进行代码重构,实现代码复用 比如现在写的是对 BookView 类进行增删改查,而当要对另一个表进行增删改查时, get、post 方法的代码都不需要改变,只需要改变雷属性 queryset 和 serializer_class 的值 """
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)