GenericAPIView具备的方法和类属性:
类属性: queryset, serializer_class
方法: get_queryset,
get_serializer, get_serialzier_class,
filter_queryset,
paginate_queryset, get_paginated_response
1.GenericAPIView
1.1 具备View的所有特性
1.2 具备APIView中的认证,授权,限流功能
1.3 支持对于获取列表数据接口的搜索,排序,分页功能
1.4 一旦继承了GenericAPIView,往往需要指定queryset,serializer_class类属性
1.4.1 queryset指定的是:当前类视图的内部的实例方法会使用的查询集对象
1..4.2 serializer指定的是:当前类视图的内部的实例方法会用到的序列化器类
1.5 实例方法中,此处调用GenericAPIView中的get_queryset()方法获取查询集对象,不直接使
用self.queryset,是因为后期我们可能重写get_queryset()方法来满足我们的需求,如果未
重写get_queryset()方法,就必须指定queryset类属性.
ps:以下示例属于未重写get_queryset()方法
1.6 实例方法中,此处调用GenericAPIView中的get_serializer()方法获取序列化器类, 一般不
直接使用self.serializer_class类属性,是因为后期我们可能重写get_serializer()方法来满
足我们的需求,如果未重写get_serializer()方法,就必须指定serializer_class类属性
ps:以上示例属于未重写get_serializer() 方法
2. 自定义路径参数,不使用pk
2.1 GenericAPIView中定义了类属性lookup_field = 'pk' 和 lookup_url_kwarg = None,
如果我们在类视图中继承了GenericAPIView,就可以重写类属性lookup_url_kwarg=自定义值
2.2 自定义值为lookup_url_kwarg = sb 以后,路径参数重我们就要使用sb
3.GenericAPIView的搜索过滤
在继承了GenericAPIView的类视图中,search_fields类属性用于指定模型类中需要进行搜索过滤的字段名.
使用icontains查询类型作为过滤类型.
可以使在字段前加相应符号,指定查询类型
如:
3.1 在全局配置文件settings.py文件中定义DEFAULT_FILTER_BACKENDS
3.2 在查询时需要使用过滤的类视图中指定 search_fields = ['字段1', '字段2'.......]
3.3 在查询实例方法get()中调用GenericAPIView的过滤方法filter_queryset(),
对查询集进行过滤,并返回过滤后的查询集
3.4 前端搜索查询
3.5 若自定义了了搜索参数,则需使用自定义搜索参数过滤
3.6 也可以在类视图中指定过滤引擎,优先级>全局配置
4.GenericAPIView的排序
a).ordering_fields类属性指定模型类中允许前端进行排序的字段名称.
b).前端默认可以使用ordering作为排序功能查询字符串参数名称,默认为该字段的生序.
c).如果字段前面添加‘-’,代表该字段降序.
d).如果指定多个字段,用英文‘,’ 分隔.
4.1 在全局配置文件settings.py指定排序引擎
4.2 在需要排序操作的类视图中指定需要排序的字段ordering_fields = ['字段1', '字段2']
4.3 前端访问
5.GenericAPIView的分页功能
5.1 在全局配置文件settings.py指定分页引擎 DEFAULT_PAGINATION_CLASS,PAGE_SIZE
5.2 在类视图中调用GenericAPIView的分页方法paginate_queryset(queryset=queryset),
返回GenericAPIView中分页特有的response:
return self.get_paginated_response(serializer.data)
5.3 输出每页跟settings.py中配置的PAGE_SIZE条数据
6. GenericAPIView中的特有过滤,排序,分页方法总结:
1.在全局配置文件setting.py中指定和rest_framework/settings.py文件中一样的配置信息.
2.在类视图中定义过滤search_fields,ordering_fields类属性.
3.在类实例方法中引用GenericAPIView一些特有的方法,如:
3.1 self.filter_queryset(queryset=queryset)
3.2 self.paginate_queryset(queryset=queryset)
return self.get_paginated_response(serializer.data)
7. 附代码
# settings.py
"""
Django settings for test_platform project.
Generated by 'django-admin startproject' using Django 4.0.4.
For more information on this file, see
https://docs.djangoproject.com/en/4.0/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/4.0/ref/settings/
"""
from pathlib import Path
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/4.0/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'django-insecure-e8n&hal3misgqk2rs*@%=ii#h)cj7_01f2(q(czi_4zf=b+%26'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = []
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
# 注册子应用
'projects',
'interfaces'
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
# 'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ROOT_URLCONF = 'test_platform.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
WSGI_APPLICATION = 'test_platform.wsgi.application'
# Database
# https://docs.djangoproject.com/en/4.0/ref/settings/#databases
DATABASES = {
# 'default': {
# 'ENGINE': 'django.db.backends.sqlite3',
# 'NAME': BASE_DIR / 'db.sqlite3',
# }
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'eyes_db',
'HOST': '127.0.0.1',
'USER': 'root',
'PASSWORD': '123456',
'PORT': '3306',
}
}
# Password validation
# https://docs.djangoproject.com/en/4.0/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
# Internationalization
# https://docs.djangoproject.com/en/4.0/topics/i18n/
LANGUAGE_CODE = 'zh-hans'
TIME_ZONE = 'Asia/Shanghai'
USE_I18N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/4.0/howto/static-files/
STATIC_URL = 'static/'
# Default primary key field type
# https://docs.djangoproject.com/en/4.0/ref/settings/#default-auto-field
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
# 指定drf中能用的各种解析器,渲染器,过滤引擎,搜索引擎,排序引擎,分页引擎等
REST_FRAMEWORK = {
# 指定全局渲染引擎
'DEFAULT_RENDERER_CLASSES': [
# 此渲染引擎,可以向前端返回json格式数据
'rest_framework.renderers.JSONRenderer',
# 可以向前端返回可浏览的API页面文档
'rest_framework.renderers.BrowsableAPIRenderer',
],
# 指定全局解析引擎
'DEFAULT_PARSER_CLASSES': [
# 解析前端传来的Json格式数据,若前端指定content-type=application/json,
# 就会使用此JSONParser解析器解析
'rest_framework.parsers.JSONParser',
# 解析前端传来的表单格式数据,若前端指定content-type=application/x-www-form-urlencoded,
# 就会使用此FormParser解析器解析
'rest_framework.parsers.FormParser',
# 解析前端传来的multipart-form-data格式数据,若前端指定content-type=multipart/form-data,
# 就会使用此MultiPartParser解析器解析
'rest_framework.parsers.MultiPartParser'
],
#1。 在全局'DEFAULT_FILTER_BACKENDS'指定使用的过滤引擎类(SearchFilter为搜索引擎类)
'DEFAULT_FILTER_BACKENDS': [
'rest_framework.filters.SearchFilter',
# 排序引擎(OrderingFilter为排序引擎类)
'rest_framework.filters.OrderingFilter',
],
# 可以在全局使用SEARCH_PARAM修改起前端过滤查询字符串参数名称(默认为search)
'SEARCH_PARAM': 'se',
# 指定分页引擎
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
# 指定每页条数
'PAGE_SIZE': 2,
}
if __name__ == '__main__':
BASE_DIR = Path(__file__).resolve()
print('111',BASE_DIR)
# projects/views.py
import json
from django.http import HttpResponse, JsonResponse
# 子应用视图
from django.views import View
from rest_framework import status, filters
from rest_framework.filters import OrderingFilter
from rest_framework.generics import GenericAPIView
from rest_framework.renderers import JSONRenderer
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.views import APIView
from projects.models import Projects
# from projects.serializers import ProjectSerializer
from projects.serializers import PorjectModelSerializer
from utils.pagination import PageNumberPagination
class JsonDecoderError111(BaseException):
"""
1.serializers.ModelSerializer提供模型对象序列化+create()方法+update()方法
2。APIView 提供从request.data中获取请求参数+返回Response()对象
"""
pass
# class ProjectsView(View):
# class ProjectsView(APIView):
class ProjectsView(GenericAPIView):
"""
继承GenericAPIView(或者其子类)的类视图
1。具备View的所有特性
2。具备APIView中的认证,授权,限流功能
3。支持对于获取列表数据接口的搜索,排序,分页功能
"""
queryset = Projects.objects.all()
serializer_class = PorjectModelSerializer
# filter_backends在继承了GenericAPIView的类视图中指定过滤引擎,优先级>全局配置
# filter_backends = [filters.SearchFilter, OrderingFilter]
# 2。 类视图中指定可用于过滤查询的字段search_fields = [xxx]
search_fields = ['^full_name', 'id']
# 配置过滤器类
filter_backends = [filters.SearchFilter, OrderingFilter]
# 排序字段
ordering_fields = ['full_name', 'leader', 'id']
# 指定自定义的分页器引擎(先导入)
pagination_class = PageNumberPagination
def get(self, request: Request):
# 查询所有项目信息
# 实例方法中,此处调用GenericAPIView中的get_queryset()方法获取查询集对象,
# 不直接使用self.queryset,是因为后期我们可能重写get_queryset()方法来满足我们的需求,
# 如果未重写get_queryset()方法,就必须指定queryset类属性
# queryset = self.get_queryset()
# 3。 此处filter.queryset,可以对查询集再过滤,返回过滤后的查询集
queryset = self.filter_queryset(queryset=self.get_queryset())
# 调用GenericAPIView的分页方法paginate_queryset(),参数为上面过滤后的查询集
page_queryset = self.paginate_queryset(queryset=queryset)
if page_queryset is not None:
# 若分页成功,返回分页处理后的Response
serializer = self.get_serializer(instance=page_queryset, many=True)
return self.get_paginated_response(serializer.data)
# 实例方法中,此处调用GenericAPIView中的get_serializer()方法获取序列化器类,
# 一般不直接使用self.serializer_class类属性,是因为后期我们可能重写get_serializer()方法来满足我们的需求,
# 如果未重写get_serializer()方法,就必须指定serializer_class类属性
serializer = self.get_serializer(instance=queryset, many=True)
return Response(serializer.data, status=status.HTTP_200_OK)
def post(self, request: Request):
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 ProjectDetailView(GenericAPIView):
get_pro_obj = Projects.objects.get
serializer_class = PorjectModelSerializer
# 自定义lookup_field 值
lookup_url_kwarg = 'sb'
# def get(self, request, pk):
def get(self, request, *args, **kwargs):
# GenericAPIView提供的get_object()方法不需要传pk
instance = self.get_object()
serializer = self.get_serializer(instance=instance)
return Response(serializer.data, status=status.HTTP_200_OK)
def put(self, request: Request, *args, **kwargs):
# 获取待更新的对象
instance = self.get_object()
serializer = self.get_serializer(instance=instance, data=request.data)
serializer.is_valid(raise_exception=True)
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
def delete(self, request: Request, *args, **kwargs):
instance = self.get_object()
count = instance.delete()
result = {
'msg': f'删除{args}成功',
'count': count,
}
return Response(data=result, status=204)
8.分页功能定制
8.1 drf的rest_framework.pagination.PageNumberPagination分页类源码:
默认只定义了页码的参数"page",没有定义每页条数参数,默认为None,我们可以对其进行二次开发,修改None为自己想要的查询字符串参数
8.2 utils中定义pagination.py文件
8.3 自定义分页控制类
8.3.1 继承drf的分页控制类
"""
自定义分页器类
"""
from django.utils.translation import gettext_lazy as _
from rest_framework.pagination import PageNumberPagination as _PageNumberPagination
class PageNumberPagination(_PageNumberPagination):
# 每页条数
page_size = 3
# 前端指定页码时可使用的查询字符串参数
page_query_param = 'page'
page_query_description = _('获取的页码.')
# 前端指定每页数据条数时可使用的查询字符串参数
page_size_query_param = 'size'
page_size_query_description = _('每一页数据条数.')
# 每页最大数据条数
max_page_size = 50
last_page_strings = ('last',)
template = 'rest_framework/pagination/numbers.html'
# 超过数据量时的提示
invalid_page_message = _('无效页码.')
8.3.2 全局配置文件中使用自定义的分页器类,不用drf的
8.3.3 在需要使用自定义分页器的类视图中使用自定义分页器,优先级>全局
8.3.4 前端输出:
8.3.5 自定义返回内容的字段
源码:
由上可知,我们前端收到的返回,受
rest_framework.pagination.PageNumberPagination.get_paginated_response()方法
控制,里面定义了给我买返回count,next,previous,results字段,所以我们需要添加返回内容
的话,就要重写该方法.
输出