20. 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
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值