DRF中有内置的serializer序列化
urls.py
url(r'^page/view/article/$', views.PageViewArticleView.as_view()),
views.py
from rest_framework.generics import ListAPIView
class PageViewArticleSerializer(serializers.ModelSerializer):
class Meta:
model = models.Article
fields = "__all__" class
class PageViewArticleView(ListAPIView):
queryset = models.Article.objects.all()
serializer_class = PageViewArticleSerializer ##内置序列化功能,但是序列化函数和功能需要自己定义
小知识扩展:类的约束
# 约束子类中必须实现f1方法
class Base(object):
def f1(self):
raise NotImplementedError('asdfasdfasdfasdf')
class Foo(Base):
def f1(self):
print(123)
obj = Foo()
obj.f1()
分页
PageNumberPagination
分页功能使用方式一
- 配置settings.py
REST_FRAMEWORK = {
"PAGE_SIZE":2
}
- 在视图的列表页面
from rest_framework.pagination import PageNumberPagination
from rest_framework import serializers
class PageArticleSerializer(serializers.ModelSerializer):
class Meta:
model = models.Article
fields = "__all__"
class PageArticleView(APIView):
def get(self,request,*args,**kwargs):
queryset =models.Article.objects.all()
# 方式一:仅数据
"""
# 分页对象
page_object = PageNumberPagination()
# 调用 分页对象.paginate_queryset方法进行分页,得到的结果是分页之后的数据
# result就是分完页的一部分数据
result = page_object.paginate_queryset(queryset,request,self)
# 序列化分页之后的数据
ser = PageArticleSerializer(instance=result,many=True)
return Response(ser.data)
"""
#方式二:数据+分页信息
"""
page_object=PageNumberPagination()
result=page_object.paginate_queryset(queryset,request,self)
ser=PageArticleSerializer(instance=result,many=True)
return page_object.get_paginated_response(ser.data)
"""
#方式三:数据+部分分页信息
page_object=PageNumberPagination()
result=page_object.paginate_queryset(queryset,request,self)
ser=PageArticleSerializer(instance=result,many=True)
return Response({'count':page_object.page.paginator.count,'result':ser.data})
分页功能使用方式二
DRF除了提供一个APIView还提供其它类供我们使用(分页功能一般和ListAPIView,CreateAPIView,....配合使用,APIView源码中没有调用分页功能)
- settings.py
## DRF内置了分页功能,需要自己配置。
# settings.py 全局配置,所有的DRF都可以使用
REST_FRAMEWORK = {
"PAGE_SIZE":2,
}
- view.py
# ListAPIView
# 继承它之后,它内部可以实现序列化和分页功能
from rest_framework.pagination import PageNumberPagination
class PageViewArticleView(ListAPIView):
queryset = models.News.objects.all()
filter_backends = [NewFilterBackend, ]
serializer_class = NewSerializers
# 自定义分页功能
pagination_class = PageNumberPagination
# 当请求来时,找get方法,自定义中没有去父类中找
class ListAPIView(mixins.ListModelMixin,GenericAPIView):
def get(self, request, *args, **kwargs):
# 执行list方法,先从自定义类寻找,没有的话就去父类寻找
return self.list(request, *args, **kwargs)
# 执行self.list方法,自定义没有从父类中寻找
class ListModelMixin:
def list(self, request, *args, **kwargs):
# get_queryset取所有queryset,然后在执行filter_queryset筛选
queryset = self.filter_queryset(self.get_queryset())
'''
class GenericAPIView(views.APIView):
def get_queryset(self):
# 取PageViewArticleView中寻找queryset
queryset = self.queryset
if isinstance(queryset, QuerySet):
queryset = queryset.all()
return queryset
# 对queryset进行筛选
def filter_queryset(self, queryset):
# 先取filter_backends,从自定义类中寻找,方法需要自定义
for backend in list(self.filter_backends):
queryset = backend().filter_queryset(self.request, queryset, self)
return queryset
'''
page = self.paginate_queryset(queryset)
'''
class GenericAPIView(views.APIView):
def paginate_queryset(self, queryset):
# 如果def paginator(self) 返回一个None则跳过筛选
—— if self.paginator is None:
| return None
# 如果不为None,则执行PageNumberPagination对象.paginate_queryset
| return self.paginator.paginate_queryset(queryset, self.request, view=self)
|
——》 @property
def paginator(self):
if not hasattr(self, '_paginator'):
# 如果自定义类中没定义pagination_class,那么_paginator = None
if self.pagination_class is None:
self._paginator = None
else:
self._paginator = self.pagination_class()
return self._paginator
'''
# 如果page不为None,执行序列化
if page is not None:
serializer = self.get_serializer(page, many=True)
'''
def get_serializer(self, *args, **kwargs):
# 从自定义类中获取serializer_class
serializer_class = self.get_serializer_class()
kwargs['context'] = self.get_serializer_context()
return serializer_class(*args, **kwargs)
def get_serializer_class(self):
return self.serializer_class
'''
return self.get_paginated_response(serializer.data)
'''
def get_paginated_response(self, data):
assert self.paginator is not None
# 返回分页和数据信息
return self.paginator.get_paginated_response(data)
'''
# 如果page为None,直接序列化之后,返回给用户
serializer = self.get_serializer(queryset, many=True)
return Response(serializer.data)
扩展
使用PageNumberPagination分页时,除了把分页写在类中,还可以放在配置中
## DRF内置了分页功能,需要自己配置。
# settings.py 全局配置:所有的DRF都可以使用
REST_FRAMEWORK = {
"PAGE_SIZE":2,
"DEFAULT_PAGINATION_CLASS":"rest_framework.pagination.PageNumberPagination"
}
class PageViewArticleView(ListAPIView):
queryset = models.Article.objects.all()
serializer_class = PageViewArticleSerializer
## DRF内置了分页功能,需要自己配置。
# 局部配置:当前类可用
REST_FRAMEWORK = {
"PAGE_SIZE":2,
}
class PageViewArticleView(ListAPIView):
queryset = models.Article.objects.all()
serializer_class = PageViewArticleSerializer
pagination_class = PageNumberPagination
LimitOffffsetPagination
# 这种不常用,建议使用上面PageNumberPagination
from rest_framework.pagination import LimitOffsetPagination
from rest_framework import serializers
class PageArticleSerializer(serializers.ModelSerializer):
class Meta:
model = models.Article
fields = "__all__"
class HulaLimitOffsetPagination(LimitOffsetPagination):
# 每次最多展示几条数据
max_limit = 2
class PageArticleView(APIView):
def get(self,request,*args,**kwargs):
queryset = models.Article.objects.all()
page_object = HulaLimitOffsetPagination()
result = page_object.paginate_queryset(queryset, request, self)
ser = PageArticleSerializer(instance=result, many=True)
return Response(ser.data)
筛选
这里我们先做个练习
常规使用筛选
model表
class UserInfo(models.Model):
""" 用户表 """
username = models.CharField(verbose_name='用户名',max_length=32)
password = models.CharField(verbose_name='密码',max_length=64)
class Article(models.Model):
""" 文章表 """
category_choices = (
(1,'咨询'),
(2,'公司动态'),
(3,'分享'),
(4,'答疑'),
(5,'其他'),
)
category = models.IntegerField(verbose_name='分类',choices=category_choices)
title = models.CharField(verbose_name='标题',max_length=32)
image = models.CharField(verbose_name='图片路径',max_length=128) # /media/upload/....
summary = models.CharField(verbose_name='简介',max_length=255)
comment_count = models.IntegerField(verbose_name='评论数',default=0)
read_count = models.IntegerField(verbose_name='浏览数',default=0)
author = models.ForeignKey(verbose_name='作者',to='UserInfo')
date = models.DateTimeField(verbose_name='创建时间',auto_now_add=True)
serializer
class ArticleListSerializer(serializers.ModelSerializer):
class Meta:
model = models.Article
fields = "__all__"
views.py
---------正常使用---------
from rest_framework.views import APIView
from rest_framework.filters import BaseFilterBackend
from rest_framework import serializers
from rest_framework.pagination import PageNumberPagination
from . import models
# 筛选类
class ArticleFilterBackend(BaseFilterBackend)
def filter_queryset(self,request,queryset,view)
val = request.query_params('cagetory')
return queryset.filter(cagetory=val)
class ArticleView(APIView):
""" 获取文章列表 """
pk = kwargs.get('pk')
# 全部数据
if not pk:
# 判断用户选择了哪个板块,并筛选出该板块的全部数据,返回给用户
queryset = models.Article.objects.all()
# 实例化筛选类对象
obj = ArticleFilterBackend()
# 执行筛选类中的filter_queryset进行序列化之后返回筛选值
queryset = obj.filter_queryset(request,queryset,self)
# 实例化分页对象
pager = PageNumberPagination()
# 将filter_queryset筛选之后的queryset分页,得到一个result结果
result = pager.paginate_queryset(queryset,request,self)
# 在将result进行序列化赋值给ser对象
ser = ArticleListSerializer(instance=result,many=True)
# 给前端返回分页后的数据
return Response(ser.data)
# 单条数据
article_object = models.Article.objects.filter(id=pk).first()
ser = PageArticleSerializer(instance=article_object,many=False)
return Response(ser.data)
上面的方法没有错,但是开发的时候很麻烦,DRF内部内置了筛选功能,供我们使用
DRF内置筛选功能
内置的筛选源码流程
---------使用内置筛选---------
class ArticleView(APIView):
""" 获取文章列表 """
queryset = models.News.objects.all()
serializer_class = NewSerializers
pagination_class = PageNumberPagination
filter_backends = [ArticleFilterBackend, ] ###内置筛选功能
# 请求来了之后走GET方法,自定义类中没有,找ListAPIView中的get方法
class ListAPIView(mixins.ListModelMixin,
GenericAPIView):
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)
class ListModelMixin:
# 执行ListModelMixin,
def list(self, request, *args, **kwargs):
# 先执行get_queryset,在执行filter_queryset筛选
queryset = self.filter_queryset(self.get_queryset())
'''
class GenericAPIView(views.APIView):
def get_queryset(self):
# 取PageViewArticleView中寻找queryset
queryset = self.queryset
if isinstance(queryset, QuerySet):
queryset = queryset.all()
return queryset
# 对queryset进行筛选
def filter_queryset(self, queryset):
# 先取filter_backends,从自定义类中寻找,筛选方法需要自定义
for backend in list(self.filter_backends):
queryset = backend().filter_queryset(self.request, queryset, self)
return 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)