序列化家族
- 序列化就是==將對象的狀態信息轉換爲能夠存儲或傳輸的形式的過程==
"""
一、Serializer類:底層序列化類 - 瞭解類
重點:單表序列化
二、ModelSerializer類:模型序列化類 - 核心類
重點:多表序列化
三、ListSerializer類:羣操做序列化類 - 輔助類
重點:輔助完成單表多表羣增羣改操做
"""
手動實現序列化
# 1.自定義序列化版本
class UserV1APIView(APIView):
def get(self, request, *args, **kwargs):
pk = kwargs.get('pk')
print(pk)
# 單查
if pk:
user_dic = models.User.objects.filter(is_delete=False, pk=pk).values('username', 'gender', 'avatar').first()
# 查詢不到時
if not user_dic:
return Response(
{'status': 1, 'msg': 'id error'},
status=status.HTTP_400_BAD_REQUEST
)
# 對頭像路徑進行拼接
user_dic['avatar'] = f"{settings.BASE_URL}{settings.MEDIA_URL}{user_dic.get('avatar')}"
return Response({
'status': 0,
'msg': 'ok',
'results': user_dic
})
# 羣查
else:
user_query = models.User.objects.filter(is_delete=False).values('username', 'gender', 'avatar')
for user_dict in user_query:
# 對頭像路徑進行拼接
user_dict['avatar'] = f"{settings.BASE_URL}{settings.MEDIA_URL}{user_dict.get('avatar')}"
user_list = list(user_query)
return Response({
'status': 0,
'msg': 'ok',
'results': user_list
})
Serializers序列化與反序列化
序列化
- 字段設置: 要同模型類的字段對應
- 自定義序列化字段:
- 字段類型爲:
SerializerMethodField()
- 字段名不該和模型類字段名衝突
- 經過定義
get_自定義字段名(self, obj)
方法來獲取要序列化的值
"""
1.新建一個serializers.py文件
2.導入: from rest_framework import serializers
3.新建一個類, 繼承serializers.Serializer
4.在類中添加須要序列化的字段, 字段名要與模型類中的字段相對應
5.自定義的字段不該該和模型類字段重名, 經過定義 'get_字段名' 方法來獲取要序列化的值
"""
# serializers.py中定義
class UserSerializer(serializers.Serializer):
# 字段名要與模型類中的字段相對應
username = serializers.CharField()
# 自定義序列化字段須要兩個參數: self和obj(模型類對象)
# 自定義序列化字段不該與模型類字段重合, 經過'get_自定義字段名'方法獲取值進行序列化
user_gender = serializers.SerializerMethodField()
def get_user_gender(self, obj):
return obj.get_gender_display()
user_avatar = serializers.SerializerMethodField()
def get_user_avatar(self, obj):
return f"{settings.BASE_URL}{settings.MEDIA_URL}{obj.avatar}"
----------------------------------------------------------------------------------------------------
"""
視圖類序列化過程
1)ORM操做獲得數據
2)將數據序列化成能夠返回給前臺的數據
3)返回數據給前臺
"""
# views.py中使用
class UserV2APIView(APIView):
def get(self, request, *args, **kwargs):
pk = kwargs.get('pk')
# 單查
if pk:
user_obj = models.User.objects.filter(is_delete=False, pk=pk).first()
# 查詢不到時
if not user_obj:
return Response(
{'status': 1, 'msg': 'id error'},
status=status.HTTP_400_BAD_REQUEST
)
# 傳入數據對象, 生成序列化對象
serializer_obj = serializers.UserSerializer(user_obj, many=False)
return Response({
'status': 0,
'msg': 'ok',
# 序列化後數據存放在序列化對象的data屬性中
'results': serializer_obj.data
})
# 羣查
user_query = models.User.objects.filter(is_delete=False).all()
# 當序列化多個數據對象時, 要設置 many=True
serializer_obj = serializers.UserSerializer(user_query, many=True)
return Response({
'status': 0,
'msg': 'ok',
# 序列化後數據存放在序列化對象的data屬性中
'results': serializer_obj.data
})
反序列化
- 自定義字段和普通字段的設置內有區別
- 自定義字段不能直接入庫, 須要設置入庫規則, 或在鉤子中將其移除
- 局部鉤子:
validate_字段名(self, value)
value是字段的值
- 經過校驗返回value, 不然拋出錯誤信息:
raise serializers.ValidationError({'字段名': '錯誤信息'})
- 全局鉤子:
validate(self, attrs)
attrs是包含字段(鍵)和字段值(值)的字典
- 經過校驗返回attrs, 不然拋出錯誤信息:
raise serializers.ValidationError({'字段名': '錯誤信息'})
- 重寫create方法實現增入庫,返回入庫成功的對象
- 重寫update方法實現改入庫,返回入庫成功的對象
# Serializer反序列化
class UserDeSerializer(serializers.Serializer):
username = serializers.CharField(min_length=3, max_length=12, error_messages={
'min_length': '不能少於三個字符',
'max_length': '不能長於12個字符',
})
password = serializers.CharField(min_length=3, error_messages={
'min_length': '不能少於三個字符',
})
# 只要有該字段, 則就必須參與反序列化, 能夠經過required=False設置不參與
gender = serializers.BooleanField(required=False)
# 自定義校驗字段, 不參於入庫操做, 須要在全局鉤子中取出
re_password = serializers.CharField(min_length=3, error_messages={
'min_length': '不能少於三個字符',
})
# 局部鉤子
def validate_username(self, value):
if value.lower() == 'bigb':
raise serializers.ValidationError('不能和我同名!')
return value
# 全局鉤子
def validate(self, attrs):
password = attrs.get('password')
re_password = attrs.pop('re_password')
if not password == re_password:
raise serializers.ValidationError({'re_password': '密碼輸入不一致'})
return attrs
# 增長操做
def create(self, validated_data):
return models.User.objects.create(**validated_data)
# 修改操做
def update(self, instance, validated_data):
# 用戶名不能被修改
validated_data.pop('username')
models.User.objects.filter(pk=instance.id).update(**validated_data)
return instance
----------------------------------------------------------------------------------------------------
"""
# 視圖類反序列化過程
# 1)從請求對象中獲取前臺提交的數據
# 2)交給序列化類完成反序列化(數據的校驗)
# 3)藉助序列化類完成數據入庫
# 4)反饋給前臺處理結果
"""
# 單增
def post(self, request, *args, **kwargs):
request_data = request.data
print(request_data)
serializer_obj = serializers.UserDeSerializer(data=request_data)
if serializer_obj.is_valid():
# 經過save()方法進行入庫
user_obj = serializer_obj.save()
return Response({
'status': 0,
'msg': 'ok',
'results': serializers.UserSerializer(user_obj).data
})
else:
return Response({
'status': 1,
'msg': serializer_obj.errors
})
ModelSerializer序列化與反序列化
- 繼承了ModelSerialzer類, 須要在配置類Meta中進行配置
- model: 綁定模型類
- field: 設置全部參與序列化與反序列化的字段
- extra_kwargs:
- 劃分系統字段爲三種: read_only, write_only, 不設置(可讀可寫)
- 字段限制條件
- 自定義序列化字段
- 在序列化類中用SerializerMethodField()來實現
- 在模型類中用@property自定義方法屬性來實現 (可插拔)
- 自定義反序列化字段:
- 同Serializer類, 且限制條件只能在此聲明, 或者在鉤子中進行判斷, 不能在extra_kwargs進行設置
- 局部鉤子和全局鉤子同Serializer類同樣
- 不須要從新create和update方法
# ModerSerializer序列化與反序列化
class UserModelSerializer(serializers.ModelSerializer):
# 第一種自定義序列化字段方法, 必須在fields中設置
# user_gender = serializers.SerializerMethodField()
#
# def get_user_gender(self, obj):
# return obj.get_gender_display()
# 自定義反序列化字段同Serializer中一致, 且校驗規則只能一併聲明, 或者在鉤子判斷, 在extra_kwargs設置無效
re_password = serializers.CharField(min_length=3,
error_messages={'min_length': '不能少於三個字符'},
write_only=True)
class Meta:
# 綁定模型表
model = models.User
# 設置全部參與序列化與反序列化的字段(插拔式設計)
fields = ('username', 'password', 'user_gender', 'gender', 'user_avatar', 're_password')
extra_kwargs = {
# 不設置write_only和read_only表名該字段可讀可寫
'username': {
'min_length': 3,
'max_length': 12,
'error_messages': {
'min_length': '不能少於3個字符',
'max_length': '不能長於12個字符',
}
},
'password': {
'write_only': True
},
'user_gender': {
# 自定義的序列化字段默認就是read_only, 且不能修改
'read_only': True
},
'gender': {
'write_only': True,
'required': False,
}
}
# 局部鉤子與Serializer一致
def validate_username(self, value):
if value.lower() == 'bigb':
raise serializers.ValidationError('不能和我同名!')
return value
# 全局鉤子與Serializer一致
def validate(self, attrs):
password = attrs.get('password')
re_password = attrs.pop('re_password')
if not password == re_password:
raise serializers.ValidationError({'re_password': '密碼輸入不一致'})
return attrs
----------------------------------------------------------------------------------------------------
# ModelSerializer序列化與反序列化
class UserV3APIView(APIView):
def get(self, request, *args, **kwargs):
pk = kwargs.get('pk')
# 單查
if pk:
user_obj = models.User.objects.filter(is_delete=False, pk=pk).first()
# 查詢不到時
if not user_obj:
return Response(
{'status': 1, 'msg': 'id error'},
status=status.HTTP_400_BAD_REQUEST
)
# 傳入數據對象, 生成序列化對象
serializer_obj = serializers.UserModelSerializer(user_obj, many=False)
return Response({
'status': 0,
'msg': 'ok',
# 序列化後數據存放在序列化對象的data屬性中
'results': serializer_obj.data
})
# 羣查
user_query = models.User.objects.filter(is_delete=False).all()
# 當序列化多個數據對象時, 要設置 many=True
serializer_obj = serializers.UserModelSerializer(user_query, many=True)
return Response({
'status': 0,
'msg': 'ok',
'results': serializer_obj.data
})
# 單增
def post(self, request, *args, **kwargs):
request_data = request.data
print(request_data)
serializer_obj = serializers.UserModelSerializer(data=request_data)
if serializer_obj.is_valid():
# 經過save()方法進行入庫
user_obj = serializer_obj.save()
return Response({
'status': 0,
'msg': 'ok',
'results': serializers.UserSerializer(user_obj).data
})
else:
return Response({
'status': 1,
'msg': serializer_obj.errors
})