增:
删:
改:
查:
DRF中的Serializer使用类定义,需要继承自rest_framework.serializers.Serializer
定义序列化器的字段与选项‘
serializer不是只能为数据库模型类定义,也可以为非数据库模型类的数据定义。serializer是独立于数据库之外的存在。
定义序列化器
创建序列化器对象
序列化器和模型类的属性要保持一致
构造方法
Serializer(instance=None,data=empty,**kwargs)
1、用于序列化时,将模型类对象传入instance参数
2、用于反序列化时,将要被反序列化的数据传入data参数
3、除了instance和data参数外,在构造Serializer对象时,还可通过context参数额外添加数据
通过context参数附加的数据,可以通过Serializer对象的context属性获取
基本使用
创建要查询的实例化对象
构造序列化器对象
如果要被序列化的是包含多条数据的查询集QuerySet,可以通过添加many=True参数补充说明
获取序列化数据
关系对象嵌套序列化
如果需要序列化的数据中包含有其他关联对象,则对关联对象数据的序列化需要指明。
对于关联字段
PrimaryKeyRelatedField
StringRelatedField
使用关联对象的序列化器
many参数
使用序列化器进行反序列化时,需要对数据进行验证后,才能获取验证成功的数据或保存成模型类对象
在获取反序列化的数据前,必须调用is_valid()方法进行验证,验证成功返回True,否则返回False
True
False
is_valid()还可以在验证失败时抛出异常serializers.ValidationError,可以通过传递raise_exception=True参数开启,REST framework接收到此异常,会向前端返回HTTP 400 Bad Request响应
在定义序列化器时,指明每个字段的序列化类型和选项参数,本身就是一种验证行为
validate_
validate
validators
在字段中添加validators选项参数,也可以补充验证行为,使用[]包裹验证的函数
语法格式
class 序列化器类(serializers.ModelSerializer)
class Meta:
model = 指明参照哪个模型类
fields = 指明为模型类的哪些字段生成
可以在shell中查看自动生成的BookInfoSerializer的具体实现
指定字段
fields
exclude
显示指明字段
指明只读字段
添加额外参数
extra_kwargs
class 序列化器类名(serializer.ModelSerializer)
class Meta:
model = 指明模型类
fileds= 指明哪些字段
extra_kwargs = {
“参数”:{},
“参数”:{},
}
DRF传入视图的request对象不再是Django默认的HttpRequest对象,而是DRF提供的扩展类的Request类的对象
DRF提供了Parser解析器,在接收请求后会自动根据Content-Type指明的请求数据类型将请求数据进行parser解析,解析为类字典对象保存到Request对象中
Request对象的数据是自动根据前端发送数据的格式进行解析之后的结果
常用属性
.data
.query_params
构造方式
Response(data,status=None,template_name=None,headers=None,content_type=None)
data
参数说明
data
status
template_name
headers
content_type
状态码
1xx 信息告知
HTTP_100_CONTINUE
HTTP_101_SWITCHING_PROTOCOLS
2xx 成功
HTTP_200_OK
HTTP_201_CREATED
HTTP_202_ACCEPTED
HTTP_203_NON_AUTHORITATIVE_INFORMATION
HTTP_204_NO_CONTENT
HTTP_205_RESET_CONTENT
HTTP_206_PARTIAL_CONTENT
HTTP_207_MULTI_STATUS
3xx 重定向
HTTP_300_MULTIPLE_CHOICES
HTTP_301_MOVED_PERMANENTLY
HTTP_302_FOUND
HTTP_303_SEE_OTHER
HTTP_304_NOT_MODIFIED
HTTP_305_USE_PROXY
HTTP_306_RESERVED
HTTP_307_TEMPORARY_REDIRECT
4xx 客户端错误
HTTP_400_BAD_REQUEST
HTTP_401_UNAUTHORIZED
HTTP_402_PAYMENT_REQUIRED
HTTP_403_FORBIDDEN
HTTP_404_NOT_FOUND
HTTP_405_METHOD_NOT_ALLOWED
HTTP_406_NOT_ACCEPTABLE
HTTP_407_PROXY_AUTHENTICATION_REQUIRED
HTTP_408_REQUEST_TIMEOUT
HTTP_409_CONFLICT
HTTP_410_GONE
HTTP_411_LENGTH_REQUIRED
HTTP_412_PRECONDITION_FAILED
HTTP_413_REQUEST_ENTITY_TOO_LARGE
HTTP_414_REQUEST_URI_TOO_LONG
HTTP_415_UNSUPPORTED_MEDIA_TYPE
HTTP_416_REQUESTED_RANGE_NOT_SATISFIABLE
HTTP_417_EXPECTATION_FAILED
HTTP_422_UNPROCESSABLE_ENTITY
HTTP_423_LOCKED
HTTP_424_FAILED_DEPENDENCY
HTTP_428_PRECONDITION_REQUIRED
HTTP_429_TOO_MANY_REQUESTS
HTTP_431_REQUEST_HEADER_FIELDS_TOO_LARGE
HTTP_451_UNAVAILABLE_FOR_LEGAL_REASONS
5xx 服务器错误
HTTP_500_INTERNAL_SERVER_ERROR
HTTP_501_NOT_IMPLEMENTED
HTTP_502_BAD_GATEWAY
HTTP_503_SERVICE_UNAVAILABLE
HTTP_504_GATEWAY_TIMEOUT
HTTP_505_HTTP_VERSION_NOT_SUPPORTED
HTTP_507_INSUFFICIENT_STORAGE
HTTP_511_NETWORK_AUTHENTICATION_REQUIRED
两个基类
APIView
定义:APIView是RESTframework提供的所有视图的基类,继承自Django的View父类
与View的不同之处
支持定义的属性
在APIView中仍以常规的类视图定义方法来实现get()、post()或者其他请求方式的方法
GenericAPIView
rest_framework.generics.GenericAPIView
1、继承自APIView,增加了对列表视图和详情视图可能用到的通用支持方法,通常使用时可以搭配一个或多个Mixin扩展类
2、支持定义的属性
列表视图与详情视图通用
列表视图使用
详情页视图使用
3、提供的方法
列表视图与详情视图通用
get_queryset(self)
get_serializer_class(self)
get_serializer(self,*args,**kwargs)
注意,在提供序列化器对象的时候,REST framework会向对象的context属性补充三个数据:request、format、view,这三个数据对象可以在定义序列化器时使用。
详情视图使用
get_object(self)
4、五个扩展类和子类视图
ListModelMixin
源代码:
class ListModelMixin(object):
“”"
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)
CreateModelMixin
class CreateModelMixin(object):
“”"
Create a model instance.
“”"
def create(self, request, *args, **kwargs):
# 获取序列化器
serializer = self.get_serializer(data=request.data)
# 验证
serializer.is_valid(raise_exception=True)
# 保存
self.perform_create(serializer)
headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
def perform_create(self, serializer):
serializer.save()
def get_success_headers(self, data):
try:
return {'Location': str(data[api_settings.URL_FIELD_NAME])}
except (TypeError, KeyError):
return {}
RetrieveModelMixin
class RetrieveModelMixin(object):
“”"
Retrieve a model instance.
“”"
def retrieve(self, request, *args, **kwargs):
# 获取对象,会检查对象的权限
instance = self.get_object()
# 序列化
serializer = self.get_serializer(instance)
return Response(serializer.data)
UpdateModelMixin
class UpdateModelMixin(object):
“”"
Update a model instance.
“”"
def update(self, request, *args, **kwargs):
partial = kwargs.pop(‘partial’, False)
instance = self.get_object()
serializer = self.get_serializer(instance, data=request.data, partial=partial)
serializer.is_valid(raise_exception=True)
self.perform_update(serializer)
if getattr(instance, '_prefetched_objects_cache', None):
# If 'prefetch_related' has been applied to a queryset, we need to
# forcibly invalidate the prefetch cache on the instance.
instance._prefetched_objects_cache = {}
return Response(serializer.data)
def perform_update(self, serializer):
serializer.save()
def partial_update(self, request, *args, **kwargs):
kwargs['partial'] = True
return self.update(request, *args, **kwargs)
DestroyModelMixin
class DestroyModelMixin(object):
“”"
Destroy a model instance.
“”"
def destroy(self, request, *args, **kwargs):
instance = self.get_object()
self.perform_destroy(instance)
return Response(status=status.HTTP_204_NO_CONTENT)
def perform_destroy(self, instance):
instance.delete()
子类视图
ListAPIView
CreateAPIView
RetireveAPIView
UpdateAPIView
DestroyAPIView
集成的子类视图
RetireveUpdateAPIView
RetrieveUpdateDestoryAPIView
使用视图集ViewSet,可以将一系列逻辑相关的动作放到一个类中:
list()
retrieve()
create()
update()
destory()
ViewSet视图集类不再实现get()、post()等方法,而是实现动作 action 如 list() 、create() 等
视图集只在使用as_view()方法的时候,才会将action动作与具体请求方式对应上
action
常用是视图集父类
ViewSet
在ViewSet中,没有提供任何动作action方法,需要我们自己实现action方法
- GenericViewSet
- 继承自GenericAPIView,作用也与GenericAPIVIew类似,提供了get_object、get_queryset等方法便于列表视图与详情信息视图的开发。
- ModelViewSet
- 继承自GenericAPIVIew,同时包括了ListModelMixin、RetrieveModelMixin、CreateModelMixin、UpdateModelMixin、DestoryModelMixin。
- ReadOnlyModelViewSet
- 继承自GenericAPIVIew,同时包括了ListModelMixin、RetrieveModelMixin。
视图集中定义添加action动作
添加自定义动作需要使用rest_framework.decorators.action装饰器
action装饰器
以action装饰器装饰的方法名会作为action动作名,与list、retrieve等同
methods
detail
表示是action中要处理的是否是视图资源的对象(即是否通过url路径获取主键)
True
False
URL的定义
路由 Routers
对于视图集ViewSet,我们除了可以自己手动指明请求方式与动作action之间的对应关系外,还可以使用Routers来帮助我们快速实现路由信息。
SimpleRouter
DefaultRouter
使用方法
1、创建router对象,并注册视图集
from rest_framework import routers
router = router.SimpleRouter()
router.register(r’路由规则’,要注册的视图集,路由名称的前缀)
对上参数说明
register(prefix, viewset, base_name)
prefix
viewset
base_name
2、添加路由数据
视图集中包含附加action的
代码:
class BookInfoViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, GenericViewSet):
queryset = BookInfo.objects.all()
serializer_class = BookInfoSerializer
@action(methods=['get'], detail=False)
def latest(self, request):
...
@action(methods=['put'], detail=True)
def read(self, request, pk):
...
最终会形成的路由
^books/latest/$ name: book-latest
^books/{pk}/read/$ name: book-read
路由router形成URL的方式
1、可以在配置文件中配置全局默认的认证方案
REST_FRAMEWORK = {
‘DEFAULT_AUTHENTICATION_CLASSES’: (
‘rest_framework.authentication.BasicAuthentication’, # 基本认证
‘rest_framework.authentication.SessionAuthentication’, # session认证
)
}
2、也可以通过在每个视图中通过设置authentication_classess属性来设置
from rest_framework.authentication import SessionAuthentication, BasicAuthentication
from rest_framework.views import APIView
class ExampleView(APIView):
authentication_classes = (SessionAuthentication, BasicAuthentication)
…
认证失败会有两种可能的返回值
权限控制可以限制用户对于视图的访问和对于具体数据对象的访问
使用
①可以在配置文件中设置默认的权限管理类
REST_FRAMEWORK = {
‘DEFAULT_PERMISSION_CLASSES’: (
‘rest_framework.permissions.IsAuthenticated’,
)
}
②如果未指明,采用这个配置
‘DEFAULT_PERMISSION_CLASSES’: (
‘rest_framework.permissions.AllowAny’,
)
③可以在具体的视图中通过permission_classes属性来设置
from rest_framework.permissions import IsAuthenticated
from rest_framework.views import APIView
class ExampleView(APIView):
permission_classes = (IsAuthenticated,)
…
提供的权限
可以对接口访问的频次进行限制,来减轻服务器压力
使用
全局配置
REST_FRAMEWORK = {
‘DEFAULT_THROTTLE_CLASSES’: (
‘rest_framework.throttling.AnonRateThrottle’,
‘rest_framework.throttling.UserRateThrottle’
),
‘DEFAULT_THROTTLE_RATES’: {
‘anon’: ‘100/day’,
‘user’: ‘1000/day’
}
}
局部使用
from rest_framework.throttling import UserRateThrottle
from rest_framework.views import APIView
class ExampleView(APIView):
throttle_classes = (UserRateThrottle,)
…
可选限流类
AnonRateThrottle
UserRateThrottle
ScopedRateThrottle
对于列表数据可能需要根据字段进行过滤,我们可以通过添加django-fitlter扩展来增强支持。
使用
下载django-filter
在配置文件中增加过滤后端的设置
INSTALLED_APPS = [
…
‘django_filters’, # 需要注册应用,
]
REST_FRAMEWORK = {
‘DEFAULT_FILTER_BACKENDS’: (‘django_filters.rest_framework.DjangoFilterBackend’,)
}
在视图中添加filter_fields属性,指定可以过滤的字段
class BookListView(ListAPIView):
queryset = BookInfo.objects.all()
serializer_class = BookInfoSerializer
filter_fields = (‘btitle’, ‘bread’)
对于列表数据,REST framework提供了OrderingFilter过滤器来帮助我们快速指明数据按照指定字段进行排序。
使用
class BookListView(ListAPIView):
queryset = BookInfo.objects.all()
serializer_class = BookInfoSerializer
filter_backends = [OrderingFilter]
ordering_fields = (‘id’, ‘bread’, ‘bpub_date’)
在类视图设置filter_backends
使用rest_framework.filters.OrderingFilter过滤器
REST framework会在请求的查询字符串参数中检查是否包含了ordering参数,
前端可以传递的ordering参数的可选字段值需要在ordering_fields中指明
全局分页
REST_FRAMEWORK = {
‘DEFAULT_PAGINATION_CLASS’: ‘rest_framework.pagination.PageNumberPagination’,
‘PAGE_SIZE’: 100 # 每页数目
}
局部分页
class LargeResultsSetPagination(PageNumberPagination):
page_size = 1000
page_size_query_param = ‘page_size’
max_page_size = 10000
可以通过自定义Pagination类,来为视图添加不同分页行为,在视图中通过pagination_class属性来指明
class BookDetailView(RetrieveAPIView):
queryset = BookInfo.objects.all()
serializer_class = BookInfoSerializer
pagination_class = LargeResultsSetPagination
如果在视图内关闭分页功能,只需在视图内设置
可选分页器
PageNumberPagination
前端访问网址形式
可以在子类中定义的属性
page_size
page_query_param
page_size_query_param
max_page_size
LimitOffsetPagination
前端访问网址形式
可以在子类中定义的属性
default_limit
limit_query_param
offset_query_param
max_limit
DRF提供了异常处理,可以自定义异常处理函数
from rest_framework.views import exception_handler
def custom_exception_handler(exc, context):
# 先调用REST framework默认的异常处理方法获得标准错误响应对象
response = exception_handler(exc, context)
# 在此处补充自定义的异常处理
if response is not None:
response.data['status_code'] = response.status_code
return response
使用
在配置文件中声明自定义的异常处理
REST_FRAMEWORK = {
‘EXCEPTION_HANDLER’: ‘my_project.my_app.utils.custom_exception_handler’
}
如果未声明,会采用默认的方式
REST_FRAMEWORK = {
‘EXCEPTION_HANDLER’: ‘rest_framework.views.exception_handler’
}
REST framework定义的异常
APIException
ParseError
AuthenticationFailed
NotAuthenticated
PermissionDenied
NotFound
MethodNotAllowed
NotAcceptable
Throttled
ValidationError
1、安装依赖
2、设置接口文档访问路径
在总路由中添加接口文档路径
文档路由对应的视图配置为rest_framework.documentation
路径
urlpatterns = [
…
url(r’^路由匹配’, include_docs_urls(接口文档网站的标题=‘My API title’))
]
3、文档描述说明的定义位置
①单一方法的视图,可直接使用诶视图的文档字符串
class BookListView(generics.ListAPIView):
“”"
返回所有图书信息.
“”"
②包含多个方法的视图,在类视图的文档字符串中,分开方法定义
class BookListCreateView(generics.ListCreateAPIView):
“”"
get:
返回所有图书信息.
post:
新建图书.
"""
③对于视图集ViewSet,仍在类视图的文档字符串中分开定义,但是应使用action名称区分
4、访问接口文档网页
XMind: ZEN - Trial Version