drf框架序列化和返序列化

0903自我總結

drf框架序列化和反序列化

from rest_framework import serializerspython

一.本身對於序列化和反序列化使用的分類

先後端交互主要有get,post,puch,put,deleter數據庫

其中用到序列化的getdjango

用到反序列化的剩下四中後端

二.序列化的使用

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類中必須存在該字段

不須要序列化字段post

  • 不須要序列化的屬性字段在序列化類中不須要聲明
  • 不須要序列化的屬性字段在序列化類中設置只寫屬性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類的多個對象的單列集合,不能是多列集合

:ui

  • 單列集合[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': '確認密碼不能爲空'
        }
    )

相較於序列化定義反序列化中增長了條件的篩選url

注意點:若是類的字段值應用在反序列化,咱們能夠在他的字段的屬性上加上write_only=Truerest

裏面所說起的字段必須傳入

經常使用的約數條件與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無論有沒有設置都不起做用

相關文章
相關標籤/搜索