写一个类继承ListAPIView
返回列表数据
class MySerializer(serializers.ModelSerializer):
class Meta:
model = models.Tag
fields = '__all__'
class MyFilterBackend(BaseFilterBackend):#BaseFilterBackend的子类必须实现filter_queryset()方法
def filter_queryset(self, request, queryset, view):
var = request.query_params.get('category')#获取/xxx/?category=?? 参数值
return queryset.filter(category=var)#将参数当作条件加入到queryset的filter()方法中
class MyAPIView(ListAPIView):
queryset = models.MyModel.objects
serializer_class = MySerializer
filter_backends = [MyFilterBackend] #可以定义多个过滤类
这样就实现了返回列表数据,如何实现的,首先查看ListAPIView
类,发现它只有一个get
方法,调用了self.list()
方法
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)
self.list()
方法在我们自己写的MyAPIView
中并没有实现,所以这时候看ListAPIView
的父类,ListAPIView
有两个父类和GenericAPIView
,根据继承顺序先看mixins.ListModelMixin
,发现有list
方法
def list(self, request, *args, **kwargs):
queryset = self.filter_queryset(self.get_queryset())
page = self.paginate_queryset(queryset)
if page is not None:
serializer = self.get_serializer(page, many=True)
return self.get_paginated_response(serializer.data)
serializer = self.get_serializer(queryset, many=True)
return Response(serializer.data)
这里面调用了self.filter_queryset()
方法,self.get_queryset()
方法,self.paginate_queryset()
方法,self.get_serializer()
方法,self.get_paginated_response()
方法,最终返回了列表数据,而这些方法在我们自己写的MyAPIView
以及ListAPIView
、mixins.ListModelMixin
中都没有定义,这时候我们看ListAPIView
的另一个父类
class GenericAPIView(views.APIView):
queryset = None #数据源
serializer_class = None #序列化器列表
filter_backends = api_settings.DEFAULT_FILTER_BACKENDS #过滤器
pagination_class = api_settings.DEFAULT_PAGINATION_CLASS #分页
def get_queryset(self): #断言如果self.queryset为空会报错,所以在我们定义的视图中必须有queryset这个属性
assert self.queryset is not None, (
"'%s' should either include a `queryset` attribute, "
"or override the `get_queryset()` method."
% self.__class__.__name__
)
queryset = self.queryset
if isinstance(queryset, QuerySet):
queryset = queryset.all() #我们自己的MyAPIView 的queryset 可以不用加all(),这里会帮我们加上
return queryset
def get_serializer_class(self): #断言如果self.serializer_class为空会报错,所以在我们定义的视图中必须有serializer_class这个属性
assert self.serializer_class is not None, (
"'%s' should either include a `serializer_class` attribute, "
"or override the `get_serializer_class()` method."
% self.__class__.__name__
)
return self.serializer_class
def get_serializer(self, *args, **kwargs):#这里实例化了我们定义的MySerializer序列化类
serializer_class = self.get_serializer_class()
return serializer_class(*args, **kwargs)
def filter_queryset(self, queryset):
#这里会循环过滤器列表,并分别调用他们的filter_queryset()方法对我们的queryset 做过滤,
#如果我们没有覆盖filter_backends属性,那么就不会做任何过滤
for backend in list(self.filter_backends):
queryset = backend().filter_queryset(self.request, queryset, self)
return queryset
@property
def paginator(self):#这里如果我们在配置文件中指定了分页器,利用反射实例化分页类
if not hasattr(self, '_paginator'):
if self.pagination_class is None:
self._paginator = None
else:
self._paginator = self.pagination_class()
return self._paginator
def paginate_queryset(self, queryset):#这里会调用分页器的paginage_querset()方法进行分页
if self.paginator is None:
return None
return self.paginator.paginate_queryset(queryset, self.request, view=self)
def get_paginated_response(self, data):
#这里对分页的数据进行了一个包装,比如我们在配置文件中指定的分页类是PageNumberPagination,
#那么会返回一个有序字典,包含count、next、previous、results 这四项内容
assert self.paginator is not None
return self.paginator.get_paginated_response(data)
看到这里,在GenericAPIView
这个类中,将我们所有的方法都已经帮我们实现了,我们只需要定义两个属性就可以完成列表数据的展示,在settings
配置文件中指定分页类就可以实现分页效果
REST_FRAMEWORK = {
'PAGE_SIZE':10, #每页显示的条数
'DEFAULT_PAGINATION_CLASS':'rest_framework.pagination.PageNumberPagination'
}
网友评论