Django--005 DRF-View

文章目录

  • 1. View
    • 1.2 简介
    • 1.1 requests对象
    • 1.2 代码
  • 2. APIView
    • 2.1 与View对比
    • 2.2 view代码
  • 3. GenericAPIView
    • 3.1 简介
    • 3.2 对比
  • 4. GenericAPIView之过滤分页排序
    • 4.1 过滤
    • 4.2 排序
    • 4.3 分页
    • 4.4 代码

1. View

1.2 简介

  • Django默认的视图基类,引用方式:from django.views import View
  • 视图views.py有两种写法,基于类或基于函数

1.1 requests对象

  • request.META:获取一个标准的python字典,它包含了所有的HTTP请求信息
  • request.scheme:请求的方式,http或https
  • request.path:请求路径
  • request.session:获取的是一个类似于字典的对象,可以进行读取写入操作
  • request.method:请求方式 POST/GET
  • request.body:获取请求数据,常见用法json.loads(request.body.decode(‘utf-8’), encoding=‘utf-8’)

1.2 代码

import json
from django.http import JsonResponse, Http404
from django.views import View
from projects.models import Projects
from projects.serializers import ProjectsModelSerializers
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status


class ProjectList(View):
    """"
    类视图
    """

    def get(self, request):
        qs = Projects.objects.all()
        # many=True: 输出querySet,返回多条数据
        serializer = ProjectsModelSerializers(instance=qs, many=True)
        return JsonResponse(serializer.data, safe=False, status=200)

    def post(self, request):
        """
        httpie模拟请求:http POST :8000/projects/ name='项目009' leader="zz" developer='李四'  tester='张三' \
                                      app_name='测试应用'  desc='demo desc'
        """
        # 1. 前端传入json数据转为python_data
        data = json.loads(request.body.decode('utf-8'), encoding='utf-8')
        # 2. 数据校验
        serializer = ProjectsModelSerializers(data=data)
        try:
            # 设置raise_exception=True后serializer.errors可以获取到报错信息
            serializer.is_valid(raise_exception=True)
        except Exception as e:
            # 3. 校验失败则返回异常dict
            return JsonResponse(serializer.errors)
        # 3. 校验通过则调用序列化器的save方法(会调用序列化器的create方法)新建数据
        serializer.save()
        # 返回新建成功的这条数据
        return JsonResponse(serializer.data, safe=False, status=201)

2. APIView

2.1 与View对比

  • APIView继承自Django的View,使用时视图需要继承APiView
  • 传入到视图的是Request对象而不是Django的HttpRequest对象
  • 视图方法可以返回Response对象,会把响应数据处理(render)为符合前段要求的格式,取决于accept这个参数
  • 任何APIException异常都会被捕获到,并且处理成合适的响应信息
  • 在进行dispatch()分发前,会对请求进行身份认证、权限检查、流量控制

2.2 view代码

# view.py
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from projects.models import Projects
from projects.serializer import ProjectModelSerializer

# 继承自APIView
class ProjectList(APIView):
    """"
    类视图
    """
    def get(self, request):
        projects = Projects.objects.all()
        serializer = ProjectModelSerializer(instance=projects, many=True)
		# 返回Response对象
        return Response(serializer.data, status=status.HTTP_200_OK)

    def post(self, request):
        """
        httpie json格式请求模拟:http POST :8000/projects/ name='项目009' leader="zz" developer='李四' tester='王五' app_name='测试应用' desc='demo desc'
        httpie form-data格式请求模拟:http -f POST :8000/projects/ name='项目009' leader="zz" developer='李四' tester='王五' app_name='测试应用' app_version='1.0' desc='demo desc'
        """
        serializer = ProjectModelSerializer(data=request.data)
        try:
            serializer.is_valid(raise_exception=True)
        except Exception as e:
            return Response(serializer.errors)
        serializer.save()
        return Response(serializer.data, status=status.HTTP_201_CREATED)

3. GenericAPIView

3.1 简介

  • 继承关系: rest_framework.generics.GenericAPIView—>rest_framework.views.APIView—>django.views.generic.base.View—>obiect—>typing.hashable
  • 必须指定的属性: queryset、serializer_class
    视图类继承自GenericAPIView后进行排序

3.2 对比

项目 View APIView GenericAPIView
继承自 Object View APIView
params获取 request.GET request.query_params request.query_params
json获取 request.body request.data request.data
data获取 request.POST request.data request.data
file获取 request.FILES request.data request.data
return JsonResponse Response request.data

4. GenericAPIView之过滤分页排序

4.1 过滤

  • 库安装
pip install django-filter
  • 注册app
INSTALLED_APPS = [
	...
    # 注册DRF子应用
    'rest_framework',
    'django_filters',
]
  • 引擎和字段配置
  • 引擎配置有类视图和全局seetings.py两种
  • 代码
# view.py
from projects.models import Projects
from projects.serializers import ProjectsModelSerializers
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework.generics import GenericAPIView
from rest_framework.response import Response
from rest_framework import status


# 1. 需要继承自GenericAPIView
class ProjectList(GenericAPIView):
    # 2.指定查询集
    queryset = Projects.objects.all()
    # 3. 指定序列化器类
    serializer_class = ProjectsModelSerializers
    # 4. 指定过滤引擎
    filter_backends = [DjangoFilterBackend]
    # 5. 指定过滤字段
    filterset_fields = ['id', 'name', 'leader']

    def get(self, request):
        """
        http://127.0.0.1:8000/projects/?id=6&name=项目5&leader=风清扬
        """
        # 动态获取查询集
        qs = self.get_queryset()
        # 过滤查询集
        qs = self.filter_queryset(qs)
        # 序列化
        serializer = self.get_serializer(instance=qs, many=True)
        # 返回列表
        return Response(serializer.data, status=status.HTTP_200_OK)

4.2 排序

  • 代码
# view.py
from django_filters.rest_framework import DjangoFilterBackend
from projects.models import Projects
from projects.serializers import ProjectsModelSerializers
from rest_framework.generics import GenericAPIView
from rest_framework.response import Response
from rest_framework import status, filters


# 1. 需要继承自GenericAPIView
class ProjectList(GenericAPIView):
    # 2.指定查询集
    queryset = Projects.objects.all()
    # 3. 指定序列化器类
    serializer_class = ProjectsModelSerializers
    # 4. 指定过滤排序引擎
    filter_backends = [DjangoFilterBackend, filters.OrderingFilter]
    # 5. 指定过滤字段
    filterset_fields = ['id', 'name', 'leader']
    # 6. 指定排序字段
    ordering_fields = ['id', 'name', 'leader']

    def get(self, request):
        """
        倒序:http://127.0.0.1:8000/projects/?ordering=-id
        """
        # 动态获取查询集
        qs = self.get_queryset()
        # 过滤查询集
        qs = self.filter_queryset(qs)
        # 序列化
        serializer = self.get_serializer(instance=qs, many=True)
        # 返回列表
        return Response(serializer.data, status=status.HTTP_200_OK)

4.3 分页

  • 约束
  • 必须指定分页引擎,可以在类视图中,也可以在全局settings.py中指定
  • 必须指定PAGE_SIZE
  • 代码
from django_filters.rest_framework import DjangoFilterBackend
from projects.models import Projects
from projects.serializers import ProjectsModelSerializers
from rest_framework.generics import GenericAPIView
from rest_framework.response import Response
from rest_framework import status, filters
from rest_framework.pagination import PageNumberPagination


# 重写分页器类,也可配置在settings.py中
# page_size必须重写
class PageNumberPaginationManual(PageNumberPagination):
    page_query_param = 'page_num'
    page_size_query_param = 'page_size'
    page_size = 2
    max_page_size = 50
    page_query_description = '第几页'
    page_size_query_description = '每页几条'


# 1. 需要继承自GenericAPIView
class ProjectList(GenericAPIView):
    # 2.指定查询集
    queryset = Projects.objects.all()
    # 3. 指定序列化器类
    serializer_class = ProjectsModelSerializers
    # # 4. 指定过滤、排序引擎
    # filter_backends = [DjangoFilterBackend, filters.OrderingFilter]
    # # 5. 指定过滤字段
    # filterset_fields = ['id', 'name', 'leader']
    # # 6. 指定排序字段
    # ordering_fields = ['id', 'name', 'leader']
    # 7. 定义分页类
    pagination_class = PageNumberPaginationManual

    def get(self, request):
        """
        分页:http://127.0.0.1:8000/projects/?page_num=3&page_size=3
        """
        # 过滤查询集
        qs = self.filter_queryset(self.get_queryset())
        # 获取分页后的查询集
        page = self.paginate_queryset(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=qs, many=True)
        return Response(serializer.data, status=status.HTTP_200_OK)

4.4 代码

  • settings.py全局配置
# settings.py

# 2. 添加'django_filters'子应用
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    # 注册子应用
    'rest_framework',
    'django_filters',
    'interfaces.apps.InterfaceConfig',
    'projects.apps.ProjectConfig'
]

# DRF配置信息
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.backends.DjangoFilterBackend']
    # 默认分页引擎
    # 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
    'DEFAULT_PAGINATION_CLASS': 'utils.pagination.PageNumberPaginationManual',
    # --设置每页展示条数
    'PAGE_SIZE': 3

}

  • 自定义分页器
# utils.pagination.py

from rest_framework.pagination import PageNumberPagination


class PageNumberPaginationManual(PageNumberPagination):
    page_query_param = 'page_num'
    page_size_query_param = 'page_size'
    # 类中page_size配置优先于settings中全局配置
    page_size = 10
    max_page_size = 50
# -*-coding:utf-8 -*-
# views.py

from projects.models import Projects
from projects.serializers import ProjectsModelSerializers
from rest_framework.generics import GenericAPIView
from rest_framework.response import Response
from rest_framework import status, filters


# 1. 需要继承自GenericAPIView
class ProjectList(GenericAPIView):
    # 2.指定查询集
    queryset = Projects.objects.all()
    # 3. 指定序列化器类
    serializer_class = ProjectsModelSerializers
    # # 4. 指定过滤、排序引擎
    # filter_backends = [DjangoFilterBackend, filters.OrderingFilter]
    # 5. 指定过滤字段
    filterset_fields = ['id', 'name', 'leader']
    # 6. 指定排序字段
    ordering_fields = ['id', 'name', 'leader']
    # 7. 定义分页类
    # pagination_class = PageNumberPaginationManual

    def get(self, request):
        """
        过滤:http://127.0.0.1:8000/projects/?id=6&name=项目5&leader=风清扬
        倒序:http://127.0.0.1:8000/projects/?ordering=-id
        分页:http://127.0.0.1:8000/projects/?ordering=name&page_num=3&page_size=3
        """
        # 过滤查询集
        qs = self.filter_queryset(self.get_queryset())
        # 获取分页后的查询集
        page = self.paginate_queryset(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=qs, many=True)
        return Response(serializer.data, status=status.HTTP_200_OK)

    def post(self, request):
        """
        httpie模拟请求:http POST :8000/projects/ name='项目009' leader="zz" developer='李四'  tester='张三' \
                                      app_name='测试应用'  desc='demo desc'
        """
        # 2. 数据校验
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        # 返回新建成功的这条数据
        return Response(serializer.data, status=status.HTTP_201_CREATED)


class ProjectDetail(GenericAPIView):
    """
    模型类继承自GenericAPIView后,无需定义get_object方法
    """
    # 2.指定查询集
    queryset = Projects.objects.all()
    # 3. 指定序列化器类
    serializer_class = ProjectsModelSerializers
    # 默认参数为pk,可以自定义
    lookup_field = 'id'

    def get(self, request, id):
        """
        httpie模拟请求:http  :8000/projects/12
        """
        qs = self.get_object()
        serializer = ProjectsModelSerializers(instance=qs)
        return Response(serializer.data, status=status.HTTP_200_OK)

    def put(self, request, id):
        """
        httpie模拟请求:http PUT :8000/projects/12 name='项目0091' leader="张三" developer='李四' \
                                tester='王五' app_name='测试应用' desc='demo desc'
        """
        # 1.判断数据是否存在
        qs = self.get_object()
        # 2. 同时存在反序列化和序列化时,同时传参会调用序列化器update方法
        serializer = self.get_serializer(instance=qs, data=request.data)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        return Response(serializer.data, status=status.HTTP_201_CREATED)

    def delete(self, request, id):
        """
        httpie模拟请求:http DELETE :8000/projects/12
        """
        # 1. 判断数据是否存在
        qs = self.get_object()
        # 2. 删除
        qs.delete()
        return Response(None, status=status.HTTP_204_NO_CONTENT)

你可能感兴趣的:(python-web,django,python,前端)