今天重新看了一遍 drf 的文档,真的是豁然开朗,以前写的时候都是不求甚解,直接 cv,现在知道为什么这么写了
技巧
- data 直接模拟来自客户端数据, 不用 request.data
- 字典用 get,不要用[],容易报错
- request.POST 的类型是 QueryDict,和普通的 Dict 不同的是,如果使用 get,只能获得数组的最后一个数,必须使用 getlist 才能获取 list
反序列化
校验数据
字段选项,都是反序列化需要
max_length min_length allow_blank trim_whitespace 截断空白符 max_value min_value
validaters = [序列化器外部的验证函数]
required = False 反序列化时可以不提供,不会报错
read_only = True 前端提交的数据不应该有这个字段,有的话被忽略 wirte_only = True 对象转化成字典时,不需要这个字段 err_message = {'min_value': '小于最小值'} 自定义验证字段报错信息
|
反序列化基本步骤
1. 实例化serializer对象 xx = XXSerializer(data=xxxx) 2. 校验数据 xx.is_valid() 3. 获取验证数据 xx.validated_data 4. 获取验证报错 xx.errors 2. 直接抛出异常,不需要4 xx.is_valid(raise_exception=True) 4. 保存 xx.save() 5. 返回 xx.validated_data
|
验证
1. 抛出异常 raise serializers.ValidationError(detail="xxxx", code="validate_name") 2. 验证来自客户端所有数据 def validate(self, attrs) 3. 验证单一字段xxx def validate_xxx(self, data)
|
保存数据
def create(self, validated_data): return xxx_model.objects.create(**validated_data) def update(self, instance, validated_data): setattr(instance, key, value) instance.save() return instance 更新操作: 1. 实例化 partial=True允许只传入部分字段更新,不验证其它字段 serializer = XXSerializer(instance=instance, data=data, partial=True) 2. 校验 xx.is_valid(raise_exception=True) 3. 保存 serializer.save() 4. 返回 serializer.validated_data
|
ModelSerializer 简化代码
class Meta: model = User fields = ['id', 'name'] exclude = [排除的字段] read_only_fields = ['id'] extra_kwargs = { '字段名': { '选项': value, }, 如: 'name': { 'max_length': 10 } } 重写create方法 def create(self, validated_data): validated_data['password'] = make_password(validated_data['password']) super().create(validated_data)
|
模型中没有声明的字段可以自己加,自己加的没有值不会返回,model 导入的一定会返回(null)
APIView
基本视图,继承自 View,升级了 request/response/as_view/异常处理方法
新增类属性:
1. authentication_classes 身份认证 2. permission_classes 权限检查 3. throttle_classes 流量控制
|
方法(需要自己写):
- get
- post
- patch
- put
- delete
request/response
request.data request.query_params request._request response(headers={'flag': '123456'})
|
GenericAPIView+Mixin
GenericAPIView 通用视图,继承自 APIView
新增类属性:
1. queryset 2. serializer_class 3. lookup_field 用于数据库查询字段名 4. lookup_url_kwarg 前端传过来的字段名
|
新增类方法:
1. get_queryset() 2. get_serializer() 多个serializer需要重写 一般不用_class的 3. get_object() 使用lookup_field参数在queryset中查/重写以提供基于多个参数查 4. filter_object()
|
Mixin 类,提供了增删查改的几个方法
1. ListModelMixin 提供list方法 2. CreateModelMixin 提供create方法 3. RetrieveModelMixin 提供查询单个对象方法 4. UpdateModelMixin 更新/partial=True部分更新 5. DestroyModelMixin 删除
|
ListAPIView
继承自 GenericAPIView 和 ListModelMixin,提供了 get 方法,里面调用了 mixin 类里的 list 方法,下面都类似,一看名字就知道了,不一一介绍了
CreateAPIView
RetrieveAPIView
DestroyAPIView
UpdateAPIView
ListCreateAPIView
RetrieveUpdateAPIView
RetrieveDestroyAPIView
RetrieveUpdateDestroyAPIView
ViewSet
继承自 APIView,更加简化代码,可以把多个相关的视图放到一块儿,搭配独特路由器机制,as_view 中绑定请求 method 到视图的方法 list/create/retrieve/update/destroy,但不提供这些方法实现,需要自己写
XXXViewSet.as_view({'get': 'list/自己的方法名···'})
|
GenericViewSet
继承自 GenericAPIView,不是 ViewSet,也是不提供 crud 方法
ModelViewSet
继承自 GenericViewSet 和所有 mixin 类,提供完整 crud 方法
RealOnlyModelViewSet
继承自 GenericViewSet+RetrieveModelMixin+ListModelMixin
Router
路由,自动绑定 method 到视图集方法
router = routers.SimpleRouter() router.register(r'users', UserViewSet) router.register(r'accounts', AccountViewSet) urlpatterns = router.urls
|
自定义方法绑定
@detail_route(methods=['post'], permission_classes=[IsAdminOrIsSelf], url_path='yyyyyy') def xxxxxx(self, request, **kwargs)
router自动生成这样的url: aaa/{pk}/yyyyyy
或者直接action绑定,和上面的类似 @action(methods, detail=True/False, url_path, url_name)
|
异常处理
自定义异常处理
from rest_framework.views import exception_handler def custom_exception_handler(exc, context): response = exception_handler(exc, context) if response is not None: response.data['status_code'] = response.status_code return response
|