Django学习 day79之drf第三日

一 修改,删除接口

views.py 的cbv下

    def put(self, request, id):
        # 通过id取到对象
        res = {'code': 100, 'msg': ''}
        try:
            book = models.Book.objects.get(id=id)

			# data: put传过来的,实现修改的数据  instance: 要被修改的对象
            ser = BookSerializer(instance=book, data=request.data)  # 这句就产生了修改后的对象
            ser.is_valid(raise_exception=True)
            ser.save()  # 将修改后的数据更新或创建到表中,这里的这个需要重写BookSerializer里的create方法
            res['msg'] = '修改成功'
            res['result'] = ser.data

        except Exception as e:
            res['code'] = 101
            res['msg'] = str(e)
        return Response(res)
        
    def delete(self,request,id):
        response = {'code': 100, 'msg': '删除成功'}
        models.Book.objects.filter(id=id).delete()
        return Response(response)

serializer.py

class BookSerializer(serializers.Serializer):
    id = serializers.IntegerField(required=False)
    title = serializers.CharField(max_length=32,min_length=2)
    price = serializers.DecimalField(max_digits=5, decimal_places=2)
    publish = serializers.CharField(max_length=32)

    def create(self, validated_data):  # 规定目标的表,并且添加字段
        res=models.Book.objects.create(**validated_data)
        print(res)
        return res

	# 修改字段的函数
    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

二 高级用法之source

  1. 修改返回到前端的字段名
    注意点: 如果想用source=title,那么字段名就不能再叫title,鱼和熊掌不可兼得
    name = serializers.CharField(max_length=32,min_length=2,source='title')
    于是乎返回给前端的字典,对应这个字段的key就是title
  2. 如果表模型中有方法
    执行表模型中的test方法,并且把返回值赋值给xxx
    xxx=serializers.CharField(source='test')
    假如text()返回的是一个字符串'我是字符串'那么前端接收的该字段对应的key就是'我是字符串'
  3. sourc支持跨表操作
    addr=serializers.CharField(source='publish.addr')
    这里实际上跨了两个表
    1. obj.publish
    2. publish.addr

三 模型类序列化器

  1. 原来用的Serilizer跟表模型没有直接联系, 模型类序列化器ModelSerilizer,跟表模型有对应关系,底层也是继承了Serilizer

  2. 使用语法

    class BookModelSerializer(serializers.ModelSerializer):
        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
        # 重写某些字段 这个必须放在Meta外面,不能放在里面
        publish = serializers.CharField(max_length=32,source='publish.name')
        # 局部钩子,全局钩子,跟原来完全一样
    
  3. 新增,修改
    统统不用重写createupdate方法了,在ModelSerializer已经重写了createupdate

四 高级用法之SerializerMethodField

# 第一种 继承Serializer的写法
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

第二种 继承ModelSerializer的写法
class BookModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Book
        fields = '__all__'
    publish = serializers.SerializerMethodField()  # 注意这俩一定要在Meta外面
    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()  # 直接套用序列化的类

    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:模板名字(一般不动),了解
headers:响应头,字典
content_type:响应的编码方式,了解

自己封装一个Response对象

class CommonResponse:
  def __init__(self):
      self.code=100
      self.msg=''
  @property
  def get_dic(self):
      return self.__dict__
  • 自己封装一个response,继承drf的Response

然后通过配置,选择默认模板的显示形式(浏览器方式,json方式)

  1. 配置文件方式(全局)
    如果没有配置,默认有浏览器和json
    -drf有默认配置文件
    from rest_framework.settings import DEFAULTS
    REST_FRAMEWORK = {
    'DEFAULT_RENDERER_CLASSES': (  # 默认响应渲染类
        'rest_framework.renderers.JSONRenderer',  # json渲染器
        'rest_framework.renderers.BrowsableAPIRenderer',  # 浏览API渲染器
    )
    }
    
  2. 在视图类中配置(局部)
    -粒度更小
    from rest_framework.renderers import JSONRenderer
    class BookDetail(APIView):
    	renderer_classes=[JSONRenderer,]  # 列表中可以导入更多
    

七 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
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值