Django1.11序列化與反序列化


django序列化與反序列化

from rest_framwork import serializers

serializers.ModelSerializer

模型類序列化器,必須依據模型類創建序列化器

  • 基於模型類自動生成一系列字段
  • 包含默認的 crate()和update()

定義ModelSerializer類

定義序列化器

  • class BookInfoSerializer(serializer.ModelSerializer):
    class Meta:
    model = BookInfo
    filels = 'all'
    read_only_fields = ('id', 'readcount', 'commentcount')
    extra_kwargs = {
    'readcount': {'min_value': 0, 'required': True},
    'commentcount': {'max_value': 0, 'required': True},
    }
    • model,指明參照的那個模型類
    • fields ,指明為模型類的那些字段生成
      • fields = ‘all’表示所有字段
      • exclude = ('iamge',) 表示排除哪些字段
      • fields = ('id','name','readcount') 表示顯示哪些字段
    • read_only_fields指明只讀字段,即僅用於序列化輸出的字段
    • extra_kwargs,為ModelSerializer添加或修改原有的選型參數
      • extra_kwargs = {
        'readcount': {'min_value': 0, 'required': True},
        'commentcount': {'max_value': 0, 'required': True},
        }

serailizers.Serializer

即可以為數據庫模型類定義,也可以為非數據庫模型類的數據定義

定義Serializer類

定義序列化器

  • class BookInfoSerializer(serializers.Serializers)
    id = serializers.IntegerField(label='ID', read_only=True)
  • 字段和選選項

創建Serializer對象

  • s = BookInfoSerializer(instance=None, data=empty, **kwarg)
    • instance:使用數據庫對象賦值,用於序列化
      data:字典類型數據,用於反序列化

序列化

  • 將程序中的數據結構類型轉換為其他類型(字典,JSON,XML)Django中將模型類轉化為JSON
  • 基本使用
    • 獲取需要序列化的對象
      • from book.models import BookInfo
        book = BookInfo.objects.get(id=4)
        • books = BookInfo.objects.all()
    • 構造序列化器對象
      • from book.serializers import BookInfoSerializer
        serializer = BookInfoSerializer(instance=book)
        • serializer = BookInfoSerializer(instace=books, many=True)
    • 獲取序列化數據
      • serializer.data
  • 關聯對象嵌套序列化
    • 如果需要序列化的數據中包含有其他關聯對象,則對關聯對象數據的序列化需要指明
    • 關聯的對象數據是一個
      • PrimaryKeyRelatedFiled
        • class PeopleInfoSerializer(serializers.Serializer):

    book = serializers.PrimaryKeyRelatedFiled(label='圖書',read_only=True)

    book = serializers.PrimaryKeyRelatedFiled(label='圖書',queryset=BookInfo.objects.all())
    * 包含read_only=True時,該字段不能用於反序列化使用
    * 包含queryset參數時,將被用作反序列化時參數校驗使用
    * 使用序列化器對象的data方法時
    對應字段顯示的是本表數據
    * {'id': 10, 'book': 3, 'description': '獨孤九劍', 'gender': 1, 'name': '令狐沖'}
    * StringRelatedFiledd
    * 此字段被序列化為關聯對象的字符串表示方式(即__str__方法的返回值)
    * book = serializers.StringRelatedFiled(label='圖書')
    * class BookInfoSerializer(serializers.serializer):
    ...
    def str(self):
    return self.name
    * 使用序列化器對象的data方法時
    對應字段顯示的關聯表__str__方法返回的數據
    * {'description': '獨孤九劍', 'name': '令狐沖', 'gender': 1, 'book': '笑傲江湖', 'id': 10}
    * 使用關聯對象的序列化器
    * book = BookInfoSerializer()
    * 使用序列化器對象的data方法時
    對應字段顯示的式OrderDict對象=有序字典
    * {'book': OrderedDict([('id', 3), ('name', '笑傲江湖'), ('pub_date', '1995-12-24'), ('readcount', 28), ('commentcount', ('image', None)]), 'gender': 1, 'name': '令狐沖', 'description': '獨孤九劍', 'id': 10}
    • 關聯對象的數據是多個
      • many參數
      • 使用django創建模型類的時候,一對多的一表有peopleinfo_set隱藏字段
      • 如果關聯對象的數據不是只有一個,而是包含多個數據,如想序列化對應數據時,此時關聯字段類型的指明仍使用上述方法,只是在聲明關聯字段時,多補充一個many=True參數即可
        • class BookInfoSerializer(serializers.Serializer):
          peopleinfo_set = serializers.PrimarykeyRelatedField(read_only=True,many=True)
  • from book.models import BookInfo

from book.serializers import BookInfoSerializer
book = BookInfo.objects.get(id=3)
serializer = BookInfoSerializer(book)
serializer.data
{'id': 3, 'peopleinfo_set': [10, 11, 12, 13], 'commentcount': 18, 'name': '笑傲江湖', 'readcount': 28, 'pub_date': '199-24', 'image': None}

反序列化

  • 與序列化相反,Django中將JSOn字符串轉化為Django中的模型類對象
  • 驗證數據
    • from book.serializers import BookInfoSerializer

data = {'pub_date':123}
serializer = BookInfoSerializer(data=data)
serializer.is_valid()
False

serializer.errors
{'pub_date': [ErrorDetail(string='Date has wrong format. Use one of these formats instead: YYYY[-MM[-DD]].', code='invalid')], 'name': [ErrorDetail(string='This field is required.', code='required')]}

serializer.validated_data
{}

* 使用序列化器進行反序列化時,需要對數據進行驗證后,才能獲取

驗證成功的數據或保存成模型類對象
* 序列化器對象調用is_valid()
* 通過字段類型和選型驗證,驗證成功返回True,失敗返回False
* is_valid(raise_exception=True)
* 驗證失敗后拋出serializers.ValidationError
* 向前端返回HTTP 400 Bad Request響應
* 自定義驗證方法
* validate_<field_name>
* 在序列化器中定義固定方法,驗證單一字段
* class BookInfoSerializer(serializers.Serializer):
"""圖書數據序列化器"""
id = serializers.IntegerField(label='ID', read_only=True)
peopleinfo_set = serializers.PrimaryKeyRelatedField(read_only=True, many=True) # 新增
def validate_readcount(self,value):
if value < 0:
raise serializers.ValidationError('閱讀數量不能為負數')
return value
* validate
* 在序列化器中定義固定方法,驗證多個字段
* class BookInfoSerializer(serializers.Serializer):
id = serializers.IntegerFiled(label='ID',read_only=True)
readcount = serializers..IntegerFiled(label='閱讀量',required=False)
commentcount = serializers..IntegerFiled(label='評論量',required=False)
def validate(self,attrs):
readcount = attrs.get('readcount')
commentcount = attrs['commentcount']
if commentcount > readcount:
raise serializers.ValidationError('評論量不能大於閱讀量')
returen attrs
* validators
* 在字段中添加validators選項參數,補充驗證行為
* class BookInfoSerializer(serializers.Serializer):

def custom_validate(value):
    raise serializers.ValidationError('我就是來搗亂的')

"""圖書數據序列化器"""
id = serializers.IntegerField(label='ID', read_only=True)
name = serializers.CharField(label='名稱', max_length=20,validators=[custom_validate])
pub_date = serializers.DateField(label='發布日期', required=False)
readcount = serializers.IntegerField(label='閱讀量', required=False)
commentcount = serializers.IntegerField(label='評論量', required=False)
image = serializers.ImageField(label='圖片', required=False)
peopleinfo_set = serializers.PrimaryKeyRelatedField(read_only=True, many=True)  # 新增
* 序列化器對象調用errors
    * 驗證失敗獲取錯誤信息
    * 驗證成功,獲取錯誤信息
* 序列化器調用validated_data
    * 驗證成功獲取數據
  • 保存

    • 如果在驗證成功后,想要基於validated_data完成數據對象的創建,可以通過實現create()和update()兩個方法來實現。
      • class BookInfoSerializer(serializers.Serializer):

    """圖書數據序列化器"""
    id = serializers.IntegerField(label='ID', read_only=True)
    name = serializers.CharField(label='名稱', max_length=20)
    pub_date = serializers.DateField(label='發布日期', required=False)
    readcount = serializers.IntegerField(label='閱讀量', required=False)
    commentcount = serializers.IntegerField(label='評論量', required=False)
    image = serializers.ImageField(label='圖片', required=False)
    peopleinfo_set = serializers.PrimaryKeyRelatedField(read_only=True, many=True) # 新增

    def create(self, validated_data):
    """新建"""
    return BookInfo(**validated_data)

    def update(self, instance, validated_data):
    """更新,instance為要更新的對象實例"""
    instance.name = validated_data.get('name', instance.name)
    instance.pub_date = validated_data.get('pub_date', instance.pub_date)
    instance.readcount = validated_data.get('readcount', instance.readcount)
    instance.commentcount = validated_data.get('commentcount', instance.commentcount)
    return instance

    • 如果需要在返回數據對象的時候,也將數據保存到數據庫中,則可以進行如下修改
      • class BookInfoSerializer(serializers.Serializer):

    """圖書數據序列化器"""
    id = serializers.IntegerField(label='ID', read_only=True)
    name = serializers.CharField(label='名稱', max_length=20)
    pub_date = serializers.DateField(label='發布日期', required=False)
    readcount = serializers.IntegerField(label='閱讀量', required=False)
    commentcount = serializers.IntegerField(label='評論量', required=False)
    image = serializers.ImageField(label='圖片', required=False)
    peopleinfo_set = serializers.PrimaryKeyRelatedField(read_only=True, many=True) # 新增

    def create(self, validated_data):
    """新建"""
    return BookInfo.objects.create(**validated_data)

    def update(self, instance, validated_data):
    """更新,instance為要更新的對象實例"""
    instance.name = validated_data.get('name', instance.name)
    instance.pub_date = validated_data.get('pub_date', instance.pub_date)
    instance.readcount = validated_data.get('readcount', instance.readcount)
    instance.commentcount = validated_data.get('commentcount', instance.commentcount)
    instance.save()
    return instance

    • 實現了上述兩個方法后,在反序列化數據的時候,就可以通過save()方法返回一個數據對象實例了
      • serializer.save()
      • 如果創建序列化器對象的時候,沒有傳遞instance實例,則調用save()方法的時候,create()被調用,相反,如果傳遞了instance實例,則調用save()方法的時候,update()被調用。

XMind: ZEN - Trial Version


免責聲明!

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



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