drf框架序列化和返序列化
0903自我总结
drf框架序列化和反序列化
from rest_framework import serializers
一.自己对于序列化和反序列化使用的分类
前后端交互主要有get
,post
,puch
,put
,deleter
其中用到序列化的get
用到反序列化的剩下四中
二.序列化的使用
1.首先我们要根据我们定义的模型一一对应定义一个继承serializers.Serializer
的类
class UserSerializer(serializers.Serializer):
username = serializers.CharField()
#不需要的字段=serializers.CharField(write_only=True)
sex = serializers.IntegerField()
gender = serializers.SerializerMethodField()
def get_gender(self, user_obj):
return user_obj.get_sex_display()
icon = serializers.SerializerMethodField() #SerializerMethodField为自定义字段
def get_icon(self, user_obj):
icon_url = 'http://127.0.0.1:8000{}{}'.format(settings.MEDIA_URL, user_obj.icon)
return icon_url
自定义字段,拿gander
字段举例在models中是
SEX_CHOICES = [
(0, '男'), #choices选择中,括号里前者表示填写的值,后者表示对应的值
(1, '女'),
]
# 为choices的字段,获取值后的映射关系 get_字段名_display()
sex = models.IntegerField(choices=SEX_CHOICES, default=0)
def get_gender(self, user_obj):
return user_obj.get_sex_display()
基于GET请求的get_固定写法
def get_model类中有字段(self,obj):
#逻辑处理
return 修改后的代码
需要序列化字段
在不做任何处理的情况下
我们定义的类里面的字段必须在model类中必须存在该字段- 参与序列化的属性名必须与model类的属性相同
- 只出现在序列化中不出现在反序列化中我们要加只读属性
read_only=True
- 如果我们Serializer类中定义字段类型为
SerializerMethodField
及自定义字段类型不用遵守类里面的字段必须在model类中必须存在该字段
不需要序列化字段
- 不需要序列化的属性字段在序列化类中不需要声明
- 不需要序列化的属性字段在序列化类中设置只写属性
write_only=True
2.在views视图中
from rest_framework.views import APIView
class UserAPIView(APIView):
def get(self, request, *args, **kwargs):
user_obj = models.User.objects.all().frist
user_obj_data = '''我们自定义的Serializer类'''(user_obj).data
return APIResponse(0, 'ok', results=user_obj_data)
- 获取models中的对象
- 我们自定义的Serializer类传入models中的对象然后
.data
- 如果models中对象为多个Serializer传入models中的对象以外
many=True
还需传入这个参数 many
这个参数默认是False所有我们序列化单个参数时候不需要传入many
- 序列化数据可以为状态User类的多个对象的
单列集合
,不能是多列集合
注
:
- 单列集合
[a,b,c.....]
|{a,b,c.....}
|(a,b,c.....)
|QuerySet
- 多列集合
{k1:v1,k2:v2.......}
三反序列化的使用
1.首先我们要根据我们定义的模型一一对应定义一个继承serializers.Serializer
的类
class UserDeserializer(serializers.Serializer):
username = serializers.CharField(
min_length=3,
error_messages={
'min_length': '用户名太短'
}
)
password = serializers.CharField(
min_length=3,
error_messages={
'min_length': '密码太短'
}
)
re_password = serializers.CharField(
min_length=3,
required=True,
error_messages={
'min_length': '确认密码太短',
'required': '确认密码不能为空'
}
)
相较于序列化定义
反序列化中增加了条件的筛选
注意点
:如果类的字段值应用在反序列化,我们可以在他的字段的属性上加上write_only=True
里面所提及的字段必须传入
常用的约数条件与django中from组件约数条件有点类似
:
error_messages
错误信息的属性required
是否为空max_length
最长min_length
最短invalid
格式
局部钩子
class UserDeserializer(serializers.Serializer):
.......
def validate_字段名称(self,value):
#代码块
if 情况不满足:
raise serializers.ValidationError('异常信息') #抛出异常
return value
#也就是对字段数据进行二次处理
全局钩子
class UserDeserializer(serializers.Serializer):
.......
def validate(self, attrs):
#attrs是所有字段的一个类似字典的集合
#我们要其中某个字段
attrs.get('字段名')
return attrs
# 最终结果抛出异常或者返回attrs
2.内容新增使用
我们如果想自定义create的相关内容我们可以Serializer类中
再加个create
方法
class UserDeserializer(serializers.Serializer):
.......
def create(self, validated_data):
try:
return modles中的类.objects.create(**validated_data)
except:
raise IOError('数据库入库失败')
我们更具需求可以先自定义一个APIResponse,继承rest_framework中的Response也可以直接使用他自带的
自定义APIResponse,建议自定义
from rest_framework.response import Response
"""
Response({
'status': 0,
'msg': 'ok',
'results': [],
'token': ''
}, headers={}, status=200, content_type="")
APIResponse(0, 'ok', results, status, headers, content_type)
"""
class APIResponse(Response):
def __init__(self, data_status, data_msg, results=None,
status=None, headers=None, content_type=None, **kwargs):
data = {
'status': data_status,
'msg': data_msg
}
if results is not None:
data['results'] = results
data.update(kwargs)
super().__init__(data=data, status=status, headers=headers, content_type=content_type)
在视图函数中的设置
class UserAPIView(APIView):
def post(self, request, *args, **kwargs): #一般都是post请求
request_data = request.data
user_ser = '''我们自定义的Serializer类'''(data=request_data) #传入request.data
if user_ser.is_valid(): # 自定义处理校验成功的逻辑
user_obj = user_ser.save()
return APIResponse(0, 'ok',
results=serializers.UserSerializer(user_obj).data
)
else: # 自定义返回错误信息
return APIResponse(1, 'failed', results=user_ser.errors)
3.内容修改使用
我们如果想自定义update的相关内容我们可以Serializer类中
再加个update
方法
class UserDeserializer(serializers.Serializer):
.......
def update(self, instance, validated_data):
# instance自定义传入的要更新的原数据(pk | obj | queryset)
# validated_data校验通过后的新数据
# instance的值外部反序列化传入要更新的自定义标识决定
instance.update(**validated_data)
return instance.first()
在视图函数中的设置
单整体改
class UserV2APIView(APIView):
def put(self, request, *args, **kwargs):
pk = kwargs.get('pk')
if not pk:
return APIResponse(1, 'pk error')
user_query = models.User.objects.filter(pk=pk, is_delete=False)
if not user_query:
return APIResponse(1, 'user error')
# 第一种:user_query完成数据的更新
# user_query = models.User.objects.filter(pk=pk)
# user_query.update(**kwargs)
# 第二种:user_obj完成数据的更新
# user_obj = models.User.objects.filter(pk=pk).first() # type: models.User
# user_obj.username = 'new_username'
# ...
# user_obj.save()
#这里的instance必须传参(pk | obj | queryset)
request_data = request.data
user_ser = serializers.UserV2Serializer(instance=user_query, data=request_data)
if user_ser.is_valid():
# save的返回值是由update内部自定义的返回值决定
user_obj = user_ser.save()
return APIResponse(0, 'ok',
results=serializers.UserV2Serializer(user_obj).data
)
else:
return APIResponse(1, 'failed', user_ser.errors)
单删
或单体修改
现在数据都是很重要的一般情况下不会吧数据删除只会做个标记字段其本质还是局部更新
def delete(self, request, *args, **kwargs):
pk = kwargs.get('pk')
if not pk:
return APIResponse(1, 'pk error')
user_obj = models.User.objects.filter(pk=pk, is_delete=False).first()
if not user_obj:
return APIResponse(1, '删除失败')
user_obj.is_delete = True
user_obj.save()
return APIResponse(0, '删除成功')
四.model字段修订与时区修改
model.py
create_time = models.DateTimeField(auto_now_add=True, null=True)
is_delete = models.BooleanField(default=False)
setting.py
时区相关设置
LANGUAGE_CODE = 'zh-hans' #其中 zh-Hans是简体中文 zh-Hant是繁体中文
TIME_ZONE = 'Asia/Shanghai' #上海时间
USE_I18N = True #国际化支持 I18N
USE_L10N = True
USE_TZ = False #USE_TZ设置为True,Django会使用系统默认设置的时区即America/Chicago,此时的TIME_ZONE不管有没有设置都不起作用。
注意点:
USE_TZ为True
,TIME_ZONE
不管有没有设置都不起作用