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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM