1. 程式人生 > >DRF框架之 serializers 序列化組件

DRF框架之 serializers 序列化組件

city 反序 hone clu 簡單 ace .... lds splay

1. 什麽是序列化,其實在python中我們就學了序列化工具json工具,就是吧信息存為類字典形式

2. DRF框架自帶序列化的工具: serializers

3. DRF框架 serializers 分為:第一種 Serializer 第二種 ModelSerializer

第一種用法之 Serializer

技術分享圖片
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() publish = models.ForeignKey(to=Publish,to_field=nid,on_delete=models.CASCADE) authors=models.ManyToManyField(to=Author) def __str__(self):
return self.name def test(self): #註意: 這裏是給後面序列化組件的source指定方法用的 return str(self.price)+self.name class Author(models.Model): nid = models.AutoField(primary_key=True) name = models.CharField(max_length=32) age = models.IntegerField() author_detail = models.OneToOneField(to=
AuthorDatail,to_field=nid,unique=True,on_delete=models.CASCADE) class AuthorDatail(models.Model): nid = models.AutoField(primary_key=True) telephone = models.BigIntegerField() birthday = models.DateField() addr = models.CharField(max_length=64) 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
models層先創建數據表 技術分享圖片
from  rest_framework import serializers
from app.models import Book,Author

####################這裏是serializers 實例化方法一的實現
#
class Bookserializer(serializers.Serializer):
    # 這裏是通過rest_framwork 來實例化對象中的內容,返回給前端的數據信息
    id = serializers.CharField()
    # source指定數據庫中的名字,前面可以自定義名字來使用,給前端顯示的是自定義名字 bookname 是自己自定義的名字
    bookname = serializers.CharField(source=name)

    price = serializers.CharField()
    # source還可以通過對象繼續點其他屬性, 可以跨表點其他的想要的屬性(這個只是拿到publish的單個字段)
    publish_name = serializers.CharField(source=publish.name)
    #註意source 還可以調用models中 Book 表內的方法
    maxprice = serializers.CharField(source=test)

#註意,source 可以名字自定義顯示,可以跨表鏈接其他想要的屬性,還可以調用book表中的自定義的方法
    # publish字段,返回出版社的所有信息,包括id,name,email。。。。
    #     #SerializerMethodField配合一個方法,方法的返回值會付給publish
    #SerializerMethodField 可以拿到跨表內的多個字段,你吧想要的都返還回去就行了(這裏是拿到publish的多個字段信息)
    publish = serializers.SerializerMethodField()
    #這裏這裏的obj 是當前序列化的對象 這裏的對象就是book!!!!
    def get_publish(self,obj):
        return {id:obj.publish.pk, name: obj.publish.name,city:obj.publish.city}

####################這裏是serializers 實例化方法一的實現
自己創建個py文件,寫上序列化顯示的內容

第二種用法之ModelSerializer

技術分享圖片
###################這裏是serializers實例化實現方法二 的實現,調用ModelSerializer
class Bookserializer(serializers.ModelSerializer):
    #這裏一個meta類去調用Book這個表
    class Meta:
        model = models.Book
        #fields  是然他顯示所有的內容,渲染出去
        fields = "__all__"         # ‘__all__‘ 是渲染全部出去
#         #fields = [‘id‘, ‘name‘]     # [‘....‘] 是渲染指定的
#         # exclude=[‘name‘]            #是除了name 之外的全部都渲染出去,不能和fields同時出現
#         #depth = 3                   #深度 ,官方建議最多寫10,深度顯示所有的表
#
    #這裏是可以自定義,自定義顯示publish的名字,
    publish_name = serializers.CharField(source=publish.name)
    publish = serializers.SerializerMethodField()
    #也可以拿到publish的多個字段信息
    def get_publish(self,obj):
        return {id:obj.publish.pk, name:obj.publish.name}

###################這裏是serializers實例化實現方法二 的實現,調用ModelSerializer
最後建議使用serializers.ModelSerializer 來實現序列化 ,因為在修改接口和添加接口 對save() 有很好的依賴關系
第二種序列化的方法(建議這種) 技術分享圖片
# 局部鉤子函數,對單個字段校驗
    #校驗name字段不能以sb開頭
    def validate_name(self,value):
        if value.startswith(sb):
            #不能讓你過
            raise ValidationError(書名不能以sb開頭)
        else:
            return value

    #全局鉤子函數,對全局字段進行校驗
    # def validate(self,a):
    #     # print(a)
    #     name=a.get(‘name‘)
    #     price=a.get(‘price‘)
    #     if name != price:
    #         raise ValidationError(‘錯了‘)
    #     else:
    #         return a
使用第二種後面還可以跟著寫局部鉤子和全局鉤子用於反序列化

最後視圖函數調用序列化的內容並返回給前端進行渲染處理

技術分享圖片
在View視圖層操作:

 查詢多本書的方法:
from rest_framework.views import APIView
from rest_framework.response import Response
from app.models import Book
from app.Myserialize import Bookserializer


class Books(APIView):  # 這個是獲取多本書的接口

    def get(self, request, *args, **kwargs):  # 這裏是通過對drf框架 使用cbv 的get請求
        response = {status: 100, msg: 獲取成功}  # 設置發送出去response 信息
        book_list = Book.objects.all()
        book_ser = Bookserializer(book_list, many=True)  # 使用drf 實例化 自定義的Bookserializer 來實例化
        response[data] = book_ser.data  # 把實例化book_ser 的data數據放入 response[‘data‘]中
        return Response(response)  # 在使用Response來返回出去

    def post(self, request):        #這個是添加書的接口
        response = {status: 100, msg: 添加成功}

        try:
            book_ser = Bookserializer(data=request.data)
            if book_ser.is_valid():         #這裏就是暈倒的反序列的內部工具和鉤子判斷
                book_ser.save()
                response[data] = book_ser.data    #判斷通過吧數據返回出去
            else:
                response[msg] = book_ser.errors
        except Exception as e:
            response[msg] = str(e)
        return Response(response)
簡單的調用序列化好的內容,並反饋給前端消息 技術分享圖片
class BookView(APIView):        #獲取單本圖書的接口
    def get(self, request, pk,*args, **kwargs):
        response = {status: 100, msg: 獲取成功}
        #取到pk為傳入的pk的書,book對象
        book = models.Book.objects.all().filter(pk=pk).first()
        #要序列化單條,many=False
        book_ser=BookSerializer(instance=book,many=False)
        # book_ser=BookSerializer(book,many=False)
        response[data]=book_ser.data


        return Response(response)


    def put(self,request,pk):     #修改某本書
        response = {status: 100, msg: 修改}
        book=models.Book.objects.filter(pk=pk).first()
        #修改
        book_ser = BookSerializer(instance=book,data=request.data)
        if book_ser.is_valid():
            book_ser.save()
            response[data]=book_ser.data
        else:
            response[msg]=book_ser.errors
        return Response(response)
接口顯示單個內容 ,主要PK是關鍵點 技術分享圖片
在路由層的配置:
urlpatterns = [
    url(r^admin/, admin.site.urls),
    url(r^books/$, views.BooksView.as_view()),    #查看全部書的接口
    url(r^books/(?P<pk>\d+), views.BookView.as_view()),   #查看單個書的接口
]
在urls 路由層進行判斷

#總結,個人建議使用第二種序列化的方法,這樣對反序列化有很好的幫助


技術分享圖片
以下是全部的接口信息

from  app import  models
from  app.Myserializers import  BookSerializers

# Create your views here.
from rest_framework.views import  APIView
from rest_framework.response import Response



class Booksview(APIView):

    def get(self,request,*args,**kwargs):       #獲取多本書
        response = {status:100, msg:查詢成功}
        book_list = models.Book.objects.all()
        book_ser = BookSerializers(book_list,many=True)
        response[data] = book_ser.data
        return Response(response)

    def post(self,request):                     #添加書
        response = {status:100, msg:添加成功}
        try:
            book_ser = BookSerializers(data=request.data)   #序列化工具拿到的數據是在request.data內的字典中獲取
            if book_ser.is_valid(): #進行鉤子判斷與基礎驗證
                book_ser.save()
                response[data] =book_ser.data
            else:
                response[msg]= book_ser.errors
        except Exception as e:
            response[msg] =str(e)
        return  Response(response)

class Bookview(APIView):

    def get(self, request, pk, *args, **kwargs):        #獲取單本書的接口
        response = {status:100 , msg: 獲取成功}
        book = models.Book.objects.all().filter(pk=pk).first()
        book_ser = BookSerializers(instance=book,many=False)
        response[data] = book_ser.data
        return  Response(response)

    def put(self, request,pk):          #修改但本書的接口
        response = {status:100, msg:修改成功}
        book = models.Book.objects.filter(pk=pk).first()
        book_ser = BookSerializers(instance=book,data=request.data)
        if book_ser.is_valid():
            book_ser.save()
            response[data]= book_ser.data
        else:
            response[msg]= book_ser.errors
        return  Response(response)

    def delete(self,request,pk):        #刪除的接口
        response = {status:100, msg: 刪除成功}
        book = models.Book.objects.filter(pk=pk).delete()
        return Response(response)
以下是通過cbv實現的簡單的五種請求的接口實現方式

DRF框架之 serializers 序列化組件