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
不管有沒有設置都不起作用