Django REST框架核心:GenericAPIView详解
Django REST framework (DRF) 中 GenericAPIView
的源码核心部分。
- 它是所有“泛型视图”的基础类,比如常用的
ListAPIView
、RetrieveAPIView
、CreateAPIView
都是继承自它。
🌟 作用
-
继承自
APIView
,因此仍然是一个标准的 DRF 视图。 -
提供了常用的“通用逻辑”:
- 统一获取 queryset
- 统一获取 serializer
- 提供 对象查找(
get_object
) - 提供 分页(
paginate_queryset
/get_paginated_response
) - 提供 过滤(
filter_queryset
)
-
它本身不实现
get/post/put/delete
等 HTTP 方法,而是作为“基类”让子类在此之上去扩展。
🔑 关键点解析
1. queryset
和 get_queryset
def get_queryset(self):assert self.queryset is not Nonequeryset = self.querysetif isinstance(queryset, QuerySet):queryset = queryset.all() # 确保每次请求都是新 QuerySetreturn queryset
- 必须设置
queryset
或重写get_queryset
。 - 一般推荐重写
get_queryset
来根据 用户/请求参数 动态返回不同数据。 - 注意不要直接用
self.queryset
,否则会因为缓存导致跨请求数据不一致。
2. serializer_class
和 get_serializer_class
def get_serializer(self, *args, **kwargs):serializer_class = self.get_serializer_class()kwargs.setdefault('context', self.get_serializer_context())return serializer_class(*args, **kwargs)
- 必须指定
serializer_class
或重写get_serializer_class
。 - 可以根据用户角色、请求方法等动态选择不同序列化器。
3. get_object
def get_object(self):queryset = self.filter_queryset(self.get_queryset())lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_fieldfilter_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
- 用来获取某一个具体对象(常用于
RetrieveAPIView
、UpdateAPIView
)。 - 默认按
pk
查找,可以改lookup_field = 'slug'
之类。 - 自动做 权限检查。
4. 过滤与分页
filter_queryset(queryset)
:遍历filter_backends
,按配置的 filter backend 处理,比如DjangoFilterBackend
、SearchFilter
、OrderingFilter
。paginate_queryset(queryset)
:按pagination_class
分页,比如PageNumberPagination
。get_paginated_response(data)
:返回带分页信息的 Response。
✅ 使用示例
比如写一个获取用户文章的 API:
from rest_framework.generics import ListAPIView, RetrieveAPIView
from .models import Article
from .serializers import ArticleSerializerclass ArticleListView(ListAPIView):serializer_class = ArticleSerializerdef get_queryset(self):# 只展示当前用户的文章return Article.objects.filter(author=self.request.user)class ArticleDetailView(RetrieveAPIView):queryset = Article.objects.all()serializer_class = ArticleSerializerlookup_field = "slug" # 用 slug 查找
这样 ListAPIView
/ RetrieveAPIView
都是基于 GenericAPIView
实现的。
👉 总结:
GenericAPIView
本身不会直接用,而是作为“可复用的基类”,把 queryset / serializer / 过滤 / 分页 / 查找对象 的逻辑抽象好,供其他泛型视图使用。