序列化組件

序列化組件

序列化之Serializers

序列化

models部分python

from django.db import models

# Create your models here.
class Book(models.Model):
    nid = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    price = models.DecimalField(max_digits=5, decimal_places=2)
    publish_date = models.DateField(null=True)
    xx=models.IntegerField(choices=((0,'文學類'),(1,'情感類')),default=1,null=True)
    publish = models.ForeignKey(to='Publish',to_field='nid',on_delete=models.CASCADE,null=True)
    authors=models.ManyToManyField(to='Author')
    def __str__(self):
        return self.name
    def test(self):
        return 'xxx'


class Author(models.Model):
    nid = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    age = models.IntegerField()



class Publish(models.Model):
    nid = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    city = models.CharField(max_length=32)
    email = models.EmailField()

    def __str__(self):
        return self.name

在app01下新建一個py文件,這裏命名爲app01serilaizergit

app01serializer部分django

from app01 import models
from rest_framework import serializers
class AuthorSerializer(serializers.Serializer):
    name=serializers.CharField()
    age=serializers.CharField()
    
class BookSerializer(serializers.Serializer):
    #指定source='name' ,表示序列化模型表中的name字段,重名命爲name5(name和source='name'指定的name不能重名)
    name5=serializers.CharField(source='name')
#     #write_only 序列化的時候,該字段不顯示
#     #read_only 反序列化的時候,該字段不傳
    price=serializers.CharField(write_only=True)
#     #若是要取 出版社的city source='publish.city'
    publish=serializers.CharField(source='publish.name')
#     #source不但能夠指定一個字段,還能夠指定一個方法
    book_type = serializers.CharField(source='get_xx_display',read_only=True)
#     #序列化出版社的詳情,指定SerializerMethodField以後,能夠對應一個方法,返回什麼內容,publish_detail就是什麼內容
    publish_detail=serializers.SerializerMethodField(read_only=True)
    #對應的方法固定寫法get_字段名
    def get_publish_detail(self,obj):
        # print(type(obj))
        return {'name':obj.publish.name,'city':obj.publish.city}  #拓展性差

    #返回全部做者信息
    authors=serializers.SerializerMethodField(read_only=True)
    def get_authors(self,obj):
        # return [ {'name':author.name,'age':author.age} for author in obj.authors.all()]
        authorser=AuthorSerializer(obj.authors.all(),many=True)  #拓展性強
        return authorser.data

    def create(self, validated_data):
        ret=models.Book.objects.create(**validated_data)
        return ret

views部分json

from app01.app01serializer import BookSerializer
class Books(APIView):
    def get(self,request):
        response={'code':100,'msg':'查詢成功'}
        books=models.Book.objects.all()
        #若是序列化多條,many=True(也就是queryset對象,就須要寫)
        #若是序列化一條(能夠不寫),instance是要序列化的對象
        bookser=BookSerializer(instance=books,many=True)
        # print(type(bookser.data))
        # bookser.data
        response['data']=bookser.data
        return Response(response)

反序列化

models部分不變app

views部分源碼分析

def post(self,request):
        #實例化產生一個序列化類的對象,data是要反序列化的字典
        # print(request.data)
        bookser=BookSerializer(data=request.data)
        if bookser.is_valid():
            #清洗經過的數據,能夠加限制好比最大長度之類的
            ret=bookser.create(bookser.validated_data)  #重寫create方法,更新的話用update

        return Response()

序列化之ModelSerializers

序列化

app01serializers部分post

from rest_framework import serializers
from rest_framework import exceptions
from app01 import models

class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model=models.Book
        # fields=('nid','name')
        #不能跟fields同時使用
        # exclude=['name',]
        fields=('__all__')
        #深度是1,官方建議不要超過10,我的建議不要超過3
        # depth=1
    # xx=serializers.CharField(source='get_xx_display')  #在外面重寫字段(取中文)
    # authors=serializers.SerializerMethodField()
    # def get_authors(self,obj):
    #     ret=AuthorSerializer(instance=obj.authors.all(),many=True)
    #     return ret.data
    # name=serializers.CharField()
    #反序列化的校驗(局部校驗,全局校驗)
    def validate_name(self,value):

        print(value)
        raise exceptions.ValidationError('不能以sb開頭')
        # if value.startswith('sb'):
        #     raise ValidationError('不能以sb開頭')
        # return value

    def validate(self,attrs):
        print(attrs)
        # if attrs.get('price')!=attrs.get('xx'):
        #     raise exceptions.ValidationError('name和price相等,不正常')
        return attrs

views部分rest

def get(self,request):
        response={'code':100,'msg':'查詢成功'}
        books=models.Book.objects.all()
        #瞭解
        # ret = serializers.serialize("json", books)
        #若是序列化多條,many=True(也就是queryset對象,就須要寫)
        #若是序列化一條(能夠不寫),instance是要序列化的對象
        bookser=BookSerializer(instance=books,many=True)
        # print(type(bookser.data))
        # bookser.data
        response['data']=bookser.data
        return Response(response)

反序列化code

views部分對象

#使用繼承了ModelSerializers序列化類的對象,反序列化
    def post(self,request):
        #實例化產生一個序列化類的對象,data是要反序列化的字典
        bookser=BookSerializer(data=request.data)
        # bookser.data
        if bookser.is_valid(raise_exception=True):
            #清洗經過的數據
            bookser.save()
        else:
            print(bookser.errors['name'][0])
        return Response()

反序列化的校驗

validate_字段名(self,value)
    若是校驗失敗,拋出validationError(拋出的異常信息須要去bookser.errors中取)
    若是校驗經過直接return value

validate(self,attrs)
    attrs全部校驗經過的數據,是個字典
    若是校驗失敗,拋出validationError
    若是校驗經過直接return attrs

源碼分析

序列化組件,先調用__new__方法,若是many=True,生成ListSerializer對象,若是爲False,生成Serializer對象
序列化對象.data方法--調用父類data方法---調用對象本身的to_representation(自定義的序列化類無此方法,去父類找)
Aerializer類裏有to_representation方法,for循環執行attribute = field.get_attribute(instance)
再去Field類裏去找get_attribute方法,self.source_attrs就是被切分的source,而後執行get_attribute方法,source_attrs
當參數傳過去,判斷是方法就加括號執行,是屬性就把值取出來
相關文章
相關標籤/搜索