Django REST framework序列化

一、關於序列化與反序列化前端

web有兩種應用模式,一種是先後端不分離,一種是先後端分離,當先後端分離的時候,後端只須要向前端傳輸數據便可,不須要進行其餘的操做;
 現階段主流的數據格式爲json格式,因此在restframework在先後端傳輸數據時,也主要是json數據,過程當中就要須要把其餘數據轉換成json數據, 好比數據庫查詢全部數據時,是queryset對象,那就要把這對象處理成json數據返回前端。


序列化與反序列化git

增:效驗請求數據 > 執行反序列化過程 > 保存數據庫 > 將保存的對象序列化並返回 刪:判斷要刪除的數據是否存在 > 執行數據庫刪除 改:判斷要修改的數據是否存在 > 效驗請求的參數 > 執行反序列化過程 > 保存數據庫 > 將保存的對象序列化並返回 查:查詢數據庫 > 將數據序列化並返回 rest-framework的序列化組件: 提供了定義序列化器Serializer的方法,能夠快速根據Django ORM 或者其餘庫自動序列化/反序列化;


二、Serializers序列化與反序列化web

序列化數據庫


-使用drf的序列化組件 -1 新建一個序列化類繼承Serializer -2 在序列化類中寫要序列化的字段 -在視圖中使用序列化的類 -1 實例化序列化的類產生對象,在產生對象的時候,傳入須要序列化的對象(queryset) -2 對象.data -3 return Response(對象.data) -高級用法: -source:能夠指定字段(name publish.name),能夠指定方法, -SerializerMethodField搭配方法使用(get_字段名字) publish_detail=serializers.SerializerMethodField(read_only=True) def get_publish_detail(self,obj): return {'name':obj.publish.name,'city':obj.publish.city} -read_only:反序列化時,不傳 -write_only:序列化時,不顯示


案例:
settings.pydjango

INSTALLED_APPS = [ ... 'rest_framework', ]


models.py中建表json

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 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

執行數據庫遷移命令;後端


在app下新建一個序列化類並繼承Serializer :app

app01serializer.py前後端分離

from rest_framework import serializers # 序列化Author的類
class AuthorSerializer(serializers.Serializer): name = serializers.CharField() age = serializers.CharField() # 序列化Book的類
class BookSerializer(serializers.Serializer): # 指定source='name',表示序列化模型表中的name字段,重名命爲name5,能夠避免直接暴露數據庫字段
    # 模型表中的字段和source指定的字段不能重名
    # name = serializers.CharField()
    name5 = serializers.CharField(source='name') # write_only 序列化的時候,該字段不顯示
    # read_only 反序列化的時候,該字段不傳
    # price = serializers.CharField()
    price = serializers.CharField(write_only=True) # 若是要取出版社的city--> source='publish.city'
    publish = serializers.CharField(source='publish.city') # source不只能夠指定一個字段,還能夠指定一個方法
    # 在modles.py的Book表中寫了一個test方法,並返回xxx
    xxx = serializers.CharField(source='test') # 好比要序列化出版社的詳情; SerializerMethodField對應着一個方法,方法返回什麼內容,publish_detail就是什麼內容
    publish_detail = serializers.SerializerMethodField() # SerializerMethodField對應的方法,固定寫法:get_字段名
    # 由於這個類是序列化Book的,參數obj就是Book對象,而後用Book對象去拿出版社的詳情
    def get_publish_detail(self, obj): print(type(obj)) return {'name':obj.publish.name, 'city':obj.publish.city} # 好比要返回全部的做者信息
    authors = serializers.SerializerMethodField() def get_authors(self, obj): # return [{'name': author.name, 'age': author.age} for author in obj.authors.all()]
        # 上面這種return的方式是用的列表推導式,當有變化時就要不斷修改這個推導式,
        # 咱們也能夠再添加一個序列化的類,當有變化時修改類就好了
        # 此時在上面添加了一個序列化Author的類,在這裏使用它
        authorser = AuthorSerializer(obj.authors.all(), many=True) return authorser.data


在視圖中使用序列化的類 :post

views.py

from app01 import models from rest_framework.views import APIView from rest_framework.serializers import Serializer
# Response本質也會是繼承了Httpresponse,可是功能更強大了 from rest_framework.response import Response # 導入新建的序列化類
from app01.app01serializer import BookSerializer # Create your views here.
class Books(APIView): def get(self, request): response = {"code":100, "msg":"查詢成功"} books = models.Book.objects.all() # 若是序列化多條,要寫many=True(序列化多條時,實際上是序列化的queryset對象 )
        # 若是序列化一條,many=True能夠不寫(序列化一條時,就不是queryset了)
        bookser = BookSerializer(books, many=True) response['data'] = bookser.data print(type(bookser.data)) return Response(response)


urls.py

from django.conf.urls import url from django.contrib import admin from app01 import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^books/', views.Books.as_view()), ]


反序列化

-使用繼承了Serializers序列化類的對象,來進行反序列化 -在本身寫的序列化類中重寫create方法 -重寫create方法,實現序列化 -在序列化類中: def create(self, validated_data): ret=models.Book.objects.create(**validated_data) return ret -在視圖中: def post(self,request): bookser=BookSerializer(data=request.data) if bookser.is_valid(): ret=bookser.create(bookser.validated_data) return Response()


在app01serializer.py的序列化Book的類中,重寫create方法:

# 序列化Book的類
class BookSerializer(serializers.Serializer): ……
 …… # 重寫create方法 def create(self, validated_data): ret = models.Book.objects.create(**validated_data) return ret


views.py

from app01 import models from rest_framework.views import APIView from rest_framework.serializers import Serializer from rest_framework.response import Response # 導入新建的序列化類
from app01.app01serializer import BookSerializer # Create your views here.
class Books(APIView): def get(self, request): response = {"code":100, "msg":"查詢成功"} books = models.Book.objects.all() # 若是序列化多條,要寫many=True(序列化多條時,實際上是序列化的queryset對象 )
        # 若是序列化一條,many=True能夠不寫(序列化一條時,就不是queryset了)
        bookser = BookSerializer(books, many=True) response['data'] = bookser.data print(type(bookser.data)) return Response(response) def post(self, request): # 實例化產生一個序列化類的對象,data是要反序列化的字典
        bookser = BookSerializer(data=request.data) if bookser.is_valid(): ret = bookser.create(bookser.validated_data) return Response()


三、ModelSerializers序列化與反序列化

序列化

app01serializer.py

from app01 import models class BookSerializer(serializers.ModelSerializer): class Meta: # 指定表模型
        model = models.Book # fields表示要序列化哪幾個字段
        # fields=('nid','name')

        # exclude表示不序列化哪些字段,不能跟fields同時使用
        # exclude=['name',]

        # __all__表示序列化全部字段
        fields = ('__all__') # 深度是1,表示能夠跨的表數量,官方建議不要超過10,我的建議不要超過3
        # 會拿到與此表深度關係爲1的表中的全部數據,且不能定製化,與下面的方式各有不一樣的使用場景
        depth=1

    # 好比要序列化全部做者的詳情信息(和Serializer中相同),這種方法能夠定製化(代碼在Meta類外面)
    # authors = serializers.SerializerMethodField()
    # def get_authors(self,obj):
    # ret = AuthorSerializer(instance=obj.authors.all(), many=True)
    # return ret.data


反序列化

#使用繼承了ModelSerializers序列化類的對象,反序列化
    #在視圖中:
        def post(self,request): bookser=BookSerializer(data=request.data) if bookser.is_valid(): ret=bookser.save() return Response()


四、反序列化的校驗

app01serializer.py

# 局部校驗
def validate_name(self,value): # value就是傳過來的值,如:name:wei 這裏的wei就是value
    print(value) raise exceptions.ValidationError('不能以sb開頭') # if value.startswith('sb'):
    # raise ValidationError('不能以sb開頭')
    # return value

#全局校驗 # 若是用了fields=('__all__')的方式,這裏的attrs可能會找不到具體的字段
def validate(self,attrs): # attrs是校驗經過的數據,是一個字典
    print(attrs) # if attrs.get('price')!=attrs.get('xx'):
    # raise exceptions.ValidationError('name和price相等,不正常')
    return attrs


views.py

class Books(APIView): def get(self,request): ... def post(self,request): #實例化產生一個序列化類的對象,data是要反序列化的字典
        bookser=BookSerializer(data=request.data) # bookser.data
        # raise_exception=True把校驗的錯誤數據拋到前端,先後端分離項目用不到
        if bookser.is_valid(raise_exception=True): #清洗經過的數據
 bookser.save() else: # 拋出校驗錯誤的信息
            print(bookser.errors['name'][0]) return Response()
相關文章
相關標籤/搜索