测试开发进阶(二十八)

欢迎关注我的公众号「测试游记」

如果前端请求头中没有指定Accept 默认返回json格式的数据

text/html

$ http -v :8000/project/1/ Accept:text/html

640?wx_fmt=jpeg

application/json

$ http -v :8000/project/1/ Accept:application/json

!返回json

使用GenericAPIView重写ProjectDetail

class ProjectDetail(GenericAPIView):	
    queryset = Projects.objects.all()	
    serializer_class = ProjectModelSerializer	
    def get(self, request, pk):	
        project = self.get_object()	
        serializer = self.get_serializer(instance=project)	
        return Response(serializer.data, status=status.HTTP_200_OK)

640?wx_fmt=jpeg

从源码中可以看到 GenericAPIView中实现了 get_object方法

def get_object(self):	
    """	
    Returns the object the view is displaying.	
    You may want to override this if you need to provide non-standard	
    queryset lookups.  Eg if objects are referenced using multiple	
    keyword arguments in the url conf.	
    """	
    queryset = self.filter_queryset(self.get_queryset())	
    # Perform the lookup filtering.	
    lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field	
    assert lookup_url_kwarg in self.kwargs, (	
        'Expected view %s to be called with a URL keyword argument '	
        'named "%s". Fix your URL conf, or set the `.lookup_field` '	
        'attribute on the view correctly.' %	
        (self.__class__.__name__, lookup_url_kwarg)	
    )	
    filter_kwargs = {self.lookup_field: self.kwargs[lookup_url_kwarg]}	
    obj = get_object_or_404(queryset, **filter_kwargs)	
    # May raise a permission denied	
    self.check_object_permissions(self.request, obj)	
    return obj

查看 self.lookup_field可以找到

lookup_field='pk'

进入 get_object_or_404可以看到一个解包,这样就拿到了查询集中 id=1的内容

640?wx_fmt=jpeg

所以使用 lookup_field类属性,可以修改传入的内容命名

  • 使用 get_serializer获取序列化器

全局指定排序

LearnDjango/settings.py中添加

REST_FRAMEWORK = {	
    "DEFAULT_RENDERER_CLASSES": (	
        # json渲染器为第一优先级	
        "rest_framework.renderers.JSONRenderer",	
        # 可浏览的API渲染为第二优先级	
        "rest_framework.renderers.BrowsableAPIRenderer",	
    ),	
    'DEFAULT_FILTER_BACKENDS': ['rest_framework.filters.OrderingFilter']	
}

过滤

安装

$ pip install django-filter

使用

添加 django_filtersAPP

INSTALLED_APPS = [	
    'django.contrib.admin',	
    'django.contrib.auth',	
    'django.contrib.contenttypes',	
    'django.contrib.sessions',	
    'django.contrib.messages',	
    'django.contrib.staticfiles',	
    'rest_framework',	
    'django_filters',	
    # 注册子应用	
    # 子应用名.apps.子应用名首字母大写Config	
    'projects.apps.ProjectsConfig',	
    'interfaces.apps.InterfacesConfig',	
    'corsheaders',	
]

projects/views.py导入

from django_filters.rest_framework import DjangoFilterBackend

projects.views.ProjectsList添加

# 5.在类视图中指定过滤引擎	
filter_backends = [DjangoFilterBackend]	
# 6.指定过滤的字段	
filterset_fields = ['name', 'leader']

查询

$ http :8000/project/ name=='测试游记1'	
zhongxindeMacBook-Pro:~ zhongxin$ http :8000/project/ name=='测试游记1'	
HTTP/1.1 200 OK	
Allow: GET, POST, HEAD, OPTIONS	
Content-Length: 130	
Content-Type: application/json	
Date: Tue, 22 Oct 2019 14:19:31 GMT	
Server: WSGIServer/0.2 CPython/3.7.1	
Vary: Accept, Origin, Cookie	
X-Frame-Options: SAMEORIGIN	
[	
    {	
        "desc": "6666",	
        "id": 2,	
        "interfaces_set": [],	
        "name": "测试游记1",	
        "programer": "zhong1",	
        "publish_app": "公众号1",	
        "tester": "zx1"	
    }	
]

640?wx_fmt=jpeg

在全局指定

REST_FRAMEWORK = {	
    "DEFAULT_RENDERER_CLASSES": (	
        # json渲染器为第一优先级	
        "rest_framework.renderers.JSONRenderer",	
        # 可浏览的API渲染为第二优先级	
        "rest_framework.renderers.BrowsableAPIRenderer",	
    ),	
    'DEFAULT_FILTER_BACKENDS': ['rest_framework.filters.OrderingFilter',	
                                'django_filters.rest_framework.DjangoFilterBackend']	
}

分页

REST_FRAMEWORK = {	
    "DEFAULT_RENDERER_CLASSES": (	
        # json渲染器为第一优先级	
        "rest_framework.renderers.JSONRenderer",	
        # 可浏览的API渲染为第二优先级	
        "rest_framework.renderers.BrowsableAPIRenderer",	
    ),	
    'DEFAULT_FILTER_BACKENDS': ['rest_framework.filters.OrderingFilter',	
                                'django_filters.rest_framework.DjangoFilterBackend'],	
    # 在全局指定分页的引擎	
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',	
    # 同时必须指定每页显示的条数	
    'PAGE_SIZE': 3,	
}

修改 projects.views.ProjectsList#get

def get(self, reuqest):	
   # 使用get_queryset获取查询集	
    project_qs = self.get_queryset() 	
    # 使用filter_queryset方法过滤查询	
    project_qs = self.filter_queryset(project_qs)  	
    # 使用paginate_queryset进行分页,然后返回分页之后的查询集	
    page = self.paginate_queryset(project_qs)  	
    if page is not None:	
        serializer = self.get_serializer(instance=page, many=True)	
        return self.get_paginated_response(serializer.data)	
    serializer = self.get_serializer(instance=project_qs, many=True)	
    return Response(serializer.data, status=status.HTTP_200_OK)

分页后

zhongxindeMacBook-Pro:~ zhongxin$ http :8000/project/	
HTTP/1.1 200 OK	
Allow: GET, POST, HEAD, OPTIONS	
Content-Length: 520	
Content-Type: application/json	
Date: Tue, 22 Oct 2019 14:41:54 GMT	
Server: WSGIServer/0.2 CPython/3.7.1	
Vary: Accept, Origin, Cookie	
X-Frame-Options: SAMEORIGIN	
{	
    "count": 5,	
    "next": "http://localhost:8000/project/?page=2",	
    "previous": null,	
    "results": [	
        {	
            "desc": "666",	
            "id": 1,	
            "interfaces_set": [	
                "Interfaces object (1)",	
                "Interfaces object (2)"	
            ],	
            "name": "测试游记",	
            "programer": "zhong",	
            "publish_app": "公众号",	
            "tester": "zx"	
        },	
        {	
            "desc": "6666",	
            "id": 2,	
            "interfaces_set": [],	
            "name": "测试游记1",	
            "programer": "zhong1",	
            "publish_app": "公众号1",	
            "tester": "zx1"	
        },	
        {	
            "desc": "666",	
            "id": 3,	
            "interfaces_set": [],	
            "name": "「测试游记」-创建",	
            "programer": "zx",	
            "publish_app": "公众号",	
            "tester": "zx"	
        }	
    ]	
}	
zhongxindeMacBook-Pro:~ zhongxin$

640?wx_fmt=jpeg

自定义分页

utils.pagination.PageNumberPaginationManual新写一个类继承于 PageNumberPagination

from rest_framework.pagination import PageNumberPagination	
class PageNumberPaginationManual(PageNumberPagination):	
    page_query_param = 'p'  # url中查询关键字从page修改为p	
    page_size = 2  # 每页显示的条数为2	
    max_page_size = 50  # 分页的最大的page_size

640?wx_fmt=jpeg

在某个类中指定分页

添加

pagination_class = PageNumberPaginationManual

再次优化

借鉴 python3.7/site-packages/rest_framework/mixins.py

查看 rest_framework.mixins.ListModelMixin

class ListModelMixin:	
    """	
    List a queryset.	
    """	
    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)

发现和 projects.views.ProjectsList#get一样

修改 get

from rest_framework import mixins	
class ProjectsList(mixins.ListModelMixin, GenericAPIView):	
    def get(self, request, *args, **kwargs):	
        return self.list(request, *args, **kwargs)

全部优化后:

from projects.models import Projects	
from projects.serializer import ProjectModelSerializer	
from rest_framework.generics import GenericAPIView	
from django_filters.rest_framework import DjangoFilterBackend	
from rest_framework import mixins	
class ProjectsList(mixins.ListModelMixin,	
                   mixins.CreateModelMixin,	
                   GenericAPIView):	
    ordering_fields = ['name', 'leader']	
    queryset = Projects.objects.all()	
    serializer_class = ProjectModelSerializer	
    filter_backends = [DjangoFilterBackend]	
    filterset_fields = ['name', 'leader', 'tester']	
    def get(self, request, *args, **kwargs):	
        return self.list(request, *args, **kwargs)	
    def post(self, request, *args, **kwargs):	
        return self.create(request, *args, **kwargs)	
class ProjectDetail(mixins.RetrieveModelMixin,	
                    mixins.UpdateModelMixin,	
                    mixins.DestroyModelMixin,	
                    GenericAPIView):	
    queryset = Projects.objects.all()	
    serializer_class = ProjectModelSerializer	
    def get(self, request, *args, **kwargs):	
        return self.retrieve(request, *args, **kwargs)	
    def put(self, request, *args, **kwargs):	
        return self.update(request, *args, **kwargs)	
    def delete(self, request, *args, **kwargs):	
        return self.destroy(request, *args, **kwargs)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值