1. 程式人生 > >drf-序列化元件 rest-framework之序列化元件

drf-序列化元件 rest-framework之序列化元件

rest-framework之序列化元件

回到目錄

一 Django自帶序列化元件

詳見

 

回到目錄

二 rest-framework序列化之Serializer

models部分:

複製程式碼
from django.db import models

# Create your models here.


class Book(models.Model):
    title=models.CharField(max_length=32)
    price=models.IntegerField()
    pub_date=models.DateField()
    publish=models.ForeignKey("
Publish") authors=models.ManyToManyField("Author") def __str__(self): return self.title class Publish(models.Model): name=models.CharField(max_length=32) email=models.EmailField() def __str__(self): return self.name class Author(models.Model): name=models.CharField(max_length=32) age
=models.IntegerField() def __str__(self): return self.name
複製程式碼

view部分:

複製程式碼
from rest_framework.views import APIView
from rest_framework.response import Response
from .models import *
from django.shortcuts import HttpResponse
from django.core import serializers


from rest_framework import serializers

class BookSerializers(serializers.Serializer):
    title=serializers.CharField(max_length=32)
    price=serializers.IntegerField()
    pub_date=serializers.DateField()
    publish=serializers.CharField(source="publish.name")
    #authors=serializers.CharField(source="authors.all")
    authors=serializers.SerializerMethodField()
    def get_authors(self,obj):
        temp=[]
        for author in obj.authors.all():
            temp.append(author.name)
        return temp
  #此處可以繼續用author的Serializers,
  # def get_authors(self,obj):
    # ret=obj.authors.all()
    # ss=AuthorSerializer(ret,many=True)
    # return ss.data
class BookViewSet(APIView): def get(self,request,*args,**kwargs): book_list=Book.objects.all() # 序列化方式1: # from django.forms.models import model_to_dict # import json # data=[] # for obj in book_list: # data.append(model_to_dict(obj)) # print(data) # return HttpResponse("ok") # 序列化方式2: # data=serializers.serialize("json",book_list) # return HttpResponse(data) # 序列化方式3: bs=BookSerializers(book_list,many=True) #many=True代表有多條資料,如果只有一條資料,many=False return Response(bs.data)
     # 序列化方式4:
   # ret=models.Book.objects.all().values('nid','title')
     # dd=list(ret)
# return HttpResponse(json.dumps(dd))


複製程式碼

注意:

source 如果是欄位,會顯示欄位,如果是方法,會執行方法,不用加括號(authors=serializers.CharField(source='authors.all'))

如在模型中定義一個方法,直接可以在在source指定執行

class UserInfo(models.Model):
    user_type_choices = (
        (1,'普通使用者'),
        (2,'VIP'),
        (3,'SVIP'),
    )
    user_type = models.IntegerField(choices=user_type_choices)

    username = models.CharField(max_length=32,unique=True)
    password = models.CharField(max_length=64)


#檢視
ret=models.UserInfo.objects.filter(pk=1).first()
aa=ret.get_user_type_display()

#serializer
xx=serializers.CharField(source='get_user_type_display')
View Code

 

回到目錄

三 rest-framework序列化之ModelSerializer

複製程式碼
class BookSerializers(serializers.ModelSerializer):
    class Meta:
        model = models.Book
        # fields = "__all__"
        fields=['nid','title','authors','publish']
        # exclude=('nid',)   #不能跟fields同時用
        # depth = 1    #深度控制,寫 幾 往裡拿幾層,層數越多,響應越慢,官方建議0--10之間,個人建議最多3層
    publish=serializers.SerializerMethodField()
    def get_publish(self,obj):
        return obj.publish.name
    authors=serializers.SerializerMethodField()
    def get_authors(self,obj):
        ret=obj.authors.all()
        ss=AuthorSerializer(ret,many=True)
        return ss.data
複製程式碼 回到目錄

四 生成hypermedialink(極少數)

複製程式碼
class BookSerializers(serializers.ModelSerializer):
    class Meta:
        model = models.Book
        fields = "__all__"
    # 生成連線,直接查看出版社詳情
    publish = serializers.HyperlinkedIdentityField(view_name='ttt', lookup_field='publish_id', lookup_url_kwarg='pkk')
    authors=serializers.SerializerMethodField()
    def get_authors(self,obj):
        ret=obj.authors.all()
        ss=AuthorSerializer(ret,many=True)
        return ss.data
#--------------

res=BookSerializers(ret,many=True,context={'request': request})
#--------------
class Publish(APIView): def get(self,request,pkk): print(pkk) return HttpResponse('ok') #----路由--- url(r'^publish/(?P<pkk>\d+)$', views.Publish.as_view(),name='ttt'),
複製程式碼 回到目錄

 五 序列化元件之請求資料校驗和儲存功能

複製程式碼
class BookSerializers(serializers.ModelSerializer):
    class Meta:
        model=Book
        fields="__all__"

#————————
class BookView(APIView):

    def post(self, request):

        # 新增一條資料
        print(request.data)

        bs=BookSerializers(data=request.data)
        if bs.is_valid():
            bs.save()  # 生成記錄
            return Response(bs.data)
        else:

            return Response(bs.errors)
複製程式碼

 

class BookSerializer1(serializers.Serializer):
    title=serializers.CharField(error_messages={'required': '標題不能為空'})

#這種方式要儲存,必須重寫create方法

 通過原始碼檢視留的校驗欄位的鉤子函式:

 

複製程式碼
    
#is_valid---->self.run_validation-(執行Serializer的run_validation)-->self.to_internal_value(data)---(執行Serializer的run_validation:485行)
def validate_title(self, value): from rest_framework import exceptions raise exceptions.ValidationError('看你不順眼') return value

#全域性
def validate(self, attrs):
from rest_framework import exceptions
if attrs.get('title')== attrs.get('title2'):
return attrs
else:
raise exceptions.ValidationError('不想等啊')
複製程式碼

 

回到目錄

序列化元件原始碼分析

序列化元件,先呼叫__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
當引數傳過去,判斷是方法就加括號執行,是屬性就把值取出來
View Code

 

圖書的增刪查改resful介面:

檢視層:

class BookSerializers(serializers.ModelSerializer):
    class Meta:
        model=models.Book
        fields='__all__'


class BookView(APIView):

    def get(self, request):
        book_list = models.Book.objects.all()
        bs = BookSerializers(book_list, many=True)
        # 序列化資料

        return Response(bs.data)

    def post(self, request):
        # 新增一條資料
        print(request.data)

        bs=BookSerializers(data=request.data)
        if bs.is_valid():
            bs.save()  # 生成記錄
            return Response(bs.data)
        else:

            return Response(bs.errors)

class BookDetailView(APIView):
    def get(self,request,pk):
        book_obj=models.Book.objects.filter(pk=pk).first()
        bs=BookSerializers(book_obj,many=False)
        return Response(bs.data)
    def put(self,request,pk):
        book_obj = models.Book.objects.filter(pk=pk).first()

        bs=BookSerializers(data=request.data,instance=book_obj)
        if bs.is_valid():
            bs.save() # update
            return Response(bs.data)
        else:
            return Response(bs.errors)
    def delete(self,request,pk):
        models.Book.objects.filter(pk=pk).delete()

        return Response("")
View Code

路由:

    url(r'^books/$', views.BookView.as_view()),
    url(r'^books/(?P<pk>\d+)$', views.BookDetailView.as_view()),
View Code

 

回到目錄

一 Django自帶序列化元件

詳見

 

回到目錄

二 rest-framework序列化之Serializer

models部分:

複製程式碼
from django.db import models

# Create your models here.


class Book(models.Model):
    title=models.CharField(max_length=32)
    price=models.IntegerField()
    pub_date=models.DateField()
    publish=models.ForeignKey("Publish")
    authors=models.ManyToManyField("Author")
    def __str__(self):
        return self.title

class Publish(models.Model):
    name=models.CharField(max_length=32)
    email=models.EmailField()
    def __str__(self):
        return self.name

class Author(models.Model):
    name=models.CharField(max_length=32)
    age=models.IntegerField()
    def __str__(self):
        return self.name
複製程式碼

view部分:

複製程式碼
from rest_framework.views import APIView
from rest_framework.response import Response
from .models import *
from django.shortcuts import HttpResponse
from django.core import serializers


from rest_framework import serializers

class BookSerializers(serializers.Serializer):
    title=serializers.CharField(max_length=32)
    price=serializers.IntegerField()
    pub_date=serializers.DateField()
    publish=serializers.CharField(source="publish.name")
    #authors=serializers.CharField(source="authors.all")
    authors=serializers.SerializerMethodField()
    def get_authors(self,obj):
        temp=[]
        for author in obj.authors.all():
            temp.append(author.name)
        return temp
  #此處可以繼續用author的Serializers,
  # def get_authors(self,obj):
    # ret=obj.authors.all()
    # ss=AuthorSerializer(ret,many=True)
    # return ss.data
class BookViewSet(APIView): def get(self,request,*args,**kwargs): book_list=Book.objects.all() # 序列化方式1: # from django.forms.models import model_to_dict # import json # data=[] # for obj in book_list: # data.append(model_to_dict(obj)) # print(data) # return HttpResponse("ok") # 序列化方式2: # data=serializers.serialize("json",book_list) # return HttpResponse(data) # 序列化方式3: bs=BookSerializers(book_list,many=True) #many=True代表有多條資料,如果只有一條資料,many=False return Response(bs.data)
     # 序列化方式4:
   # ret=models.Book.objects.all().values('nid','title')
     # dd=list(ret)
# return HttpResponse(json.dumps(dd))


複製程式碼

注意:

source 如果是欄位,會顯示欄位,如果是方法,會執行方法,不用加括號(authors=serializers.CharField(source='authors.all'))

如在模型中定義一個方法,直接可以在在source指定執行

class UserInfo(models.Model):
    user_type_choices = (
        (1,'普通使用者'),
        (2,'VIP'),
        (3,'SVIP'),
    )
    user_type = models.IntegerField(choices=user_type_choices)

    username = models.CharField(max_length=32,unique=True)
    password = models.CharField(max_length=64)


#檢視
ret=models.UserInfo.objects.filter(pk=1).first()
aa=ret.get_user_type_display()

#serializer
xx=serializers.CharField(source='get_user_type_display')
View Code

 

回到目錄

三 rest-framework序列化之ModelSerializer

複製程式碼
class BookSerializers(serializers.ModelSerializer):
    class Meta:
        model = models.Book
        # fields = "__all__"
        fields=['nid','title','authors','publish']
        # exclude=('nid',)   #不能跟fields同時用
        # depth = 1    #深度控制,寫 幾 往裡拿幾層,層數越多,響應越慢,官方建議0--10之間,個人建議最多3層
    publish=serializers.SerializerMethodField()
    def get_publish(self,obj):
        return obj.publish.name
    authors=serializers.SerializerMethodField()
    def get_authors(self,obj):
        ret=obj.authors.all()
        ss=AuthorSerializer(ret,many=True)
        return ss.data
複製程式碼 回到目錄

四 生成hypermedialink(極少數)

複製程式碼
class BookSerializers(serializers.ModelSerializer):
    class Meta:
        model = models.Book
        fields = "__all__"
    # 生成連線,直接查看出版社詳情
    publish = serializers.HyperlinkedIdentityField(view_name='ttt', lookup_field='publish_id', lookup_url_kwarg='pkk')
    authors=serializers.SerializerMethodField()
    def get_authors(self,obj):
        ret=obj.authors.all()
        ss=AuthorSerializer(ret,many=True)
        return ss.data
#--------------

res=BookSerializers(ret,many=True,context={'request': request})
#--------------
class Publish(APIView): def get(self,request,pkk): print(pkk) return HttpResponse('ok') #----路由--- url(r'^publish/(?P<pkk>\d+)$', views.Publish.as_view(),name='ttt'),
複製程式碼 回到目錄

 五 序列化元件之請求資料校驗和儲存功能

複製程式碼
class BookSerializers(serializers.ModelSerializer):
    class Meta:
        model=Book
        fields="__all__"

#————————
class BookView(APIView):

    def post(self, request):

        # 新增一條資料
        print(request.data)

        bs=BookSerializers(data=request.data)
        if bs.is_valid():
            bs.save()  # 生成記錄
            return Response(bs.data)
        else:

            return Response(bs.errors)
複製程式碼

 

class BookSerializer1(serializers.Serializer):
    title=serializers.CharField(error_messages={'required': '標題不能為空'})

#這種方式要儲存,必須重寫create方法

 通過原始碼檢視留的校驗欄位的鉤子函式:

 

複製程式碼
    
#is_valid---->self.run_validation-(執行Serializer的run_validation)-->self.to_internal_value(data)---(執行Serializer的run_validation:485行)
def validate_title(self, value): from rest_framework import exceptions raise exceptions.ValidationError('看你不順眼') return value

#全域性
def validate(self, attrs):
from rest_framework import exceptions
if attrs.get('title')== attrs.get('title2'):
return attrs
else:
raise exceptions.ValidationError('不想等啊')
複製程式碼

 

回到目錄

序列化元件原始碼分析

序列化元件,先呼叫__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
當引數傳過去,判斷是方法就加括號執行,是屬性就把值取出來
View Code

 

圖書的增刪查改resful介面:

檢視層:

class BookSerializers(serializers.ModelSerializer):
    class Meta:
        model=models.Book
        fields='__all__'


class BookView(APIView):

    def get(self, request):
        book_list = models.Book.objects.all()
        bs = BookSerializers(book_list, many=True)
        # 序列化資料

        return Response(bs.data)

    def post(self, request):
        # 新增一條資料
        print(request.data)

        bs=BookSerializers(data=request.data)
        if bs.is_valid():
            bs.save()  # 生成記錄
            return Response(bs.data)
        else:

            return Response(bs.errors)

class BookDetailView(APIView):
    def get(self,request,pk):
        book_obj=models.Book.objects.filter(pk=pk).first()
        bs=BookSerializers(book_obj,many=False)
        return Response(bs.data)
    def put(self,request,pk):
        book_obj = models.Book.objects.filter(pk=pk).first()

        bs=BookSerializers(data=request.data,instance=book_obj)
        if bs.is_valid():
            bs.save() # update
            return Response(bs.data)
        else:
            return Response(bs.errors)
    def delete(self,request,pk):
        models.Book.objects.filter(pk=pk).delete()

        return Response("")
View Code

路由:

    url(r'^books/$', views.BookView.as_view()),
    url(r'^books/(?P<pk>\d+)$', views.BookDetailView.as_view()),
View Code