drf的序列化器
一、修改和删除操作的接口
views.py
def delete(self, request, id, *args, **kwargs):
dic = {'code':100, 'msg':'删除成功'}
book = models.Book.objects.filter(pk=id).first()
book.delete()
return Response(dic)
# 修改一个指定的对象
def put(self, request, id, *args, **kwargs):
dic = {'code': 100, 'msg': ''}
try:
book = models.Book.objects.get(id=id)
ser = BookSerializer(instance=book, data=request.data)
ser.is_valid(raise_exception=True)
ser.save()
dic['msg'] = '修改成功'
dic['result'] = ser.data
except Exception as e:
dic['msg'] = '修改失败'
dic['msg'] = str(e)
return Response(dic)
serializer.py
class BookSerializer(serializers.Serializer):
id = serializers.IntegerField(required=False)
title = serializers.CharField(max_length=32)
publish = serializers.CharField(max_length=32, validators=[check])
price = serializers.DecimalField(max_digits=6, decimal_places=2)
# 必须重写create方法(源码检测到没有重写会直接抛异常)
def create(self, validated_data):
return models.Book.objects.create(**validated_data)
# 必须重写update方法
def update(self, book, validated_data):
book.title = validated_data.get('title')
book.price = validated_data.get('price')
book.publish = validated_data.get('publish')
book.save()
return book
二、高级用法——sourse
1 修改返回到前端的字段名
# 用了source=title 字段名就不能再用title
name = serializers.CharField(max_length=32,min_length=2,source='title')
2 如果表模型中有方法
# 序列化器会执行表模型中的test方法,并且把返回值赋值给xxx
test_res = serializers.CharField(source='test', read_only=True)
3 source支持跨表操作
addr = serializers.CharField(source='publish.addr',read_only=True)
三、模型类序列化器
#1 - Serilizer跟表模型没有直接联系,
- 模型类序列化器ModelSerilizer,跟表模型有对应关系
#2 使用
class BookModelSerializer(serializers.ModelSerializer):
# 重写某些字段
publish = serializers.CharField(max_length=32,source='publish.name')
class Meta:
model=表模型 # 跟哪个表模型建立关系
# fields=[字段,字段] # 序列化的字段,反序列化的字段
# fields='__all__' # 所有字段都序列化,反序列化
exclude=[字段,字段] # 排除哪些字段(不能跟fields同时使用)
# read_only_fields=['price','publish'] # 序列化显示的字段
# write_only_fields=['title'] # 反序列化需要传入的字段
extra_kwargs ={'title':{'max_length':32,'write_only':True}} # 可以替代上面两行
depth=1 # 了解,跨表1查询,最多建议写3(影响效率,使用的时候就不需要重写publish字段)
# 局部钩子,全局钩子,跟原来完全一样
#3 新增,修改
-统统不用重写create和update方法了,ModelSerializer源码中已经重写了create和update
四、高级用法——SerializerMethodField
# 方式一
class BookSerializer(serializers.Serializer):
id = serializers.IntegerField(required=False)
name = serializers.CharField(max_length=32,min_length=2,source='title')
price = serializers.DecimalField(max_digits=5, decimal_places=2)
publish = serializers.SerializerMethodField()
# 上面这句 需要下面这个配套函数
def get_publish(self,obj):
dic={'name':obj.publish.name,'addr':obj.publish.addr}
return dic
# 方式二
class BookModelSerializer(serializers.ModelSerializer):
class Meta:
model = models.Book
fields = '__all__'
publish = serializers.SerializerMethodField()
# 上面这句 需要下面这个配套函数
def get_publish(self,obj):
dic={'name':obj.publish.name,'addr':obj.publish.addr}
return dic
## 第三中方案,使用序列化类的嵌套
class PublishSerializer(serializers.ModelSerializer):
class Meta:
model = models.Publish
# fields = '__all__'
fields = ['name','addr']
class BookModelSerializer(serializers.ModelSerializer):
publish = PublishSerializer()
# 上面这句 要配套一个PublishSerializer
class Meta:
model = models.Book
fields = '__all__'
五、drf的请求与响应
# Request
- data:前端以post请求提交的数据都在它里面
- FILES:前端提交的文件
- query_params:就是之前的request.GET
- 重写了__getattr__
-使用新的request.method,其实就是取的原生request.method(通过反射实现)
# Response
- from rest_framework.response import Response
- data:响应的字典
- status:http响应的状态码
-drf提供了所有的状态码,以及它的含义
from rest_framework.status import HTTP_201_CREATED
- template_name:模板名字,(就是rest_framework提供的默认浏览器页面,一般不改动)
- head:响应头(字典)
- content_type:响应的编码方式
# 自己封装一个Response对象
class CommonResponse:
def __init__(self):
self.code = 100
self.msg = ''
@property
def get_dic(self):
return self.__dict__
# 自己封装一个response,继承drf的Response
# 通过配置,选择默认模板的显示形式(浏览器API渲染方式/json格式)
- 配置文件方式(全局)
- 如果没有配置,默认用浏览器和json
from rest_framework.settings import DEFAULTS
REST_FRAMEWORK = {
'DEFAULT_RENDERER_CLASSES': ( # 默认响应渲染类
'rest_framework.renderers.JSONRenderer', # json渲染器
'rest_framework.renderers.BrowsableAPIRenderer', # 浏览API渲染器
)
}
- 在视图类中配置(局部)
- 粒度更小
- class BookDetail(APIview):
renderer_classes=[JSONRenderder,]
六、many=True、局部全局钩子——源码解析
1、 many=True
__init__ --->一路找到了BaseSerializer--->__new__决定了生成的对象是谁
2 入口是is_valid()---》BaseSerializer--》is_valid---》self._validated_data = self.run_validation(self.initial_data)
-Serializer这个类的:self.run_validation
def run_validation(self, data=empty):
value = self.to_internal_value(data) # 局部字段自己的校验和局部钩子校验
try:
self.run_validators(value)
value = self.validate(value) # 全局钩子的校验
except (ValidationError, DjangoValidationError) as exc:
raise ValidationError(detail=as_serializer_error(exc))
return value