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
- 修改返回到前端的字段名
注意点: 如果想用source=title
,那么字段名就不能再叫title
,鱼和熊掌不可兼得
name = serializers.CharField(max_length=32,min_length=2,source='title')
于是乎返回给前端的字典,对应这个字段的key就是title
了 - 如果表模型中有方法
执行表模型中的test
方法,并且把返回值赋值给xxx
xxx=serializers.CharField(source='test')
假如text()
返回的是一个字符串'我是字符串'
那么前端接收的该字段对应的key就是'我是字符串'
了 - sourc支持跨表操作
addr=serializers.CharField(source='publish.addr')
这里实际上跨了两个表obj.publish
publish.addr
三 模型类序列化器
-
原来用的
Serilizer
跟表模型没有直接联系, 模型类序列化器ModelSerilize
r,跟表模型有对应关系,底层也是继承了Serilizer
-
使用语法
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') # 局部钩子,全局钩子,跟原来完全一样
-
新增,修改
统统不用重写create
和update
方法了,在ModelSerializer
已经重写了create
和update
四 高级用法之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方式)
- 配置文件方式(全局)
如果没有配置,默认有浏览器和json
-drf有默认配置文件from rest_framework.settings import DEFAULTS REST_FRAMEWORK = { 'DEFAULT_RENDERER_CLASSES': ( # 默认响应渲染类 'rest_framework.renderers.JSONRenderer', # json渲染器 'rest_framework.renderers.BrowsableAPIRenderer', # 浏览API渲染器 ) }
- 在视图类中配置(局部)
-粒度更小from rest_framework.renderers import JSONRenderer class BookDetail(APIView): renderer_classes=[JSONRenderer,] # 列表中可以导入更多
七 many=True源码分析,局部全局钩子源码解析
-
many=True
__init__
----->一路找到了BaseSerialize
r—》__new__
决定了生成的对象是谁 -
入口是
is_valid()
—》BaseSerialize
r–》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