11 多表關聯的序列化和反序列化
阿新 • • 發佈:2021-12-22
1.模型類序列化器ModelSerializer
publish單表基於ModelSerializer寫的5個介面
models.py
from django.db import models #### 圖書表 出版社 作者 作者詳情 圖書和作者的多對多表 # 一對多:關係一旦確立,關係欄位寫在多的一方 # 多對多:需要有中間表 class Book(models.Model): title = models.CharField(max_length=32) price = models.DecimalField(max_digits=5, decimal_places=2)# on_delete: # models.CASCADE # 級聯刪除 # models.DO_NOTHING # 什麼都不做 # models.SET_DEFAULT # 設定為預設值 # models.SET_NULL # 設定為空 # models.SET # 可以寫一個函式記憶體地址,刪除的時候,觸發這個函式執行 publish = models.ForeignKey(to='Publish', on_delete=models.SET_NULL, null=True) authors = models.ManyToManyField(to='Author') class Publish(models.Model): name = models.CharField(max_length=16) address = models.CharField(max_length=64) class Author(models.Model): name = models.CharField(max_length=16) sex = models.IntegerField(choices=[(0, '男'), (1, '女')], default=0) class AuthorDetail(models.Model): mobile= models.CharField(max_length=11) author = models.OneToOneField(to='Author', on_delete=models.CASCADE) # OneToOneField 本質就是 ForeignKey+unique
urls.py
from django.contrib import admin from django.urls import path from app01 import views urlpatterns = [ path('admin/', admin.site.urls), path('publish/',views.PublishView.as_view()), path('publish/<int:pk>',views.PublishDetailView.as_view()), ]
views.py
from rest_framework.views import APIView from rest_framework.response import Response from .models import Publish from .seriazlizer import PublishSerializer class PublishView(APIView): def get(self, request): publish_list = Publish.objects.all() ser = PublishSerializer(instance=publish_list, many=True) return Response(data=ser.data) def post(self, request): ser = PublishSerializer(data=request.data) if ser.is_valid(): ser.save() return Response(ser.data) else: return Response(ser.errors) # ser.is_valid(raise_exception=True) class PublishDetailView(APIView): def get(self, request, pk): publish = Publish.objects.all().filter(pk=pk).first() ser = PublishSerializer(instance=publish) return Response(data=ser.data) def put(self, request, pk): publish = Publish.objects.all().filter(pk=pk).first() # 資料不存在 ,None,如果instance是None,ser.save -->是新增 ser = PublishSerializer(data=request.data, instance=publish) if ser.is_valid(): ser.save() return Response(ser.data) else: return Response(ser.errors) # ser.is_valid(raise_exception=True) def delete(self, request, pk): res = Publish.objects.all().filter(pk=pk).delete() # 返回影響的行數 if res >= 1: return Response() else: return Response('要刪除的資料不存在')
serializer.py(模型類序列化器ModelSerializer)
class PublishSerializer(serializers.ModelSerializer): class Meta: model = Publish fields = "__all__"
publish單表通過postman操作post,get,put,delete
2,圖書的多表關聯的序列化和反序列化的5個介面
views.py
############# 圖書的多表關聯的5個介面 from .models import Book, AuthorDetail, Author from .seriazlizer import BookSerializer class BookView(APIView): def get(self, request): book_list = Book.objects.all() ser = BookSerializer(instance=book_list, many=True) return Response(data=ser.data) def post(self, request): ser = BookSerializer(data=request.data) if ser.is_valid(): ser.save() return Response(ser.data) else: return Response(ser.errors) # ser.is_valid(raise_exception=True) class BookDetailView(APIView): def get(self, request, pk): book = Book.objects.all().filter(pk=pk).first() ser = BookSerializer(instance=book) return Response(data=ser.data) def put(self, request, pk): book = Book.objects.all().filter(pk=pk).first() # 資料不存在 ,None,如果instance是None,ser.save -->是新增 ser = BookSerializer(data=request.data, instance=book) if ser.is_valid(): ser.save() return Response(ser.data) else: return Response(ser.errors) # ser.is_valid(raise_exception=True) def delete(self, request, pk): res = Book.objects.all().filter(pk=pk).delete() # 返回影響的行數 if res >= 1: return Response() else: return Response('要刪除的資料不存在')
urls.py
from django.contrib import admin from django.urls import path from app01 import views urlpatterns = [ path('admin/', admin.site.urls), path('book/', views.BookView.as_view()), path('book/<int:pk>', views.BookDetailView.as_view()), ]
方式一:在表模型中寫方法,在序列化類的fields宣告一下就可以
models.py
from django.db import models class Book(models.Model): title = models.CharField(max_length=32) price = models.DecimalField(max_digits=5, decimal_places=2) # on_delete: # models.CASCADE # 級聯刪除 # models.DO_NOTHING # 什麼都不做 # models.SET_DEFAULT # 設定為預設值 # models.SET_NULL # 設定為空 # models.SET # 可以寫一個函式記憶體地址,刪除的時候,觸發這個函式執行 publish = models.ForeignKey(to='Publish', on_delete=models.SET_NULL, null=True) authors = models.ManyToManyField(to='Author') @property # 加不加都行 def publish_detail(self): return {'name':self.publish.name,'address':self.publish.address} # 作者詳情 在列表套字典 def author_detail(self): # 獲取所有的作者 author_list=self.authors.all() author_dict_list = [] for author in author_list: author_dict_list.append({'name':author.name,'sex':author.get_sex_display()}) return author_dict_list
serializers.py
from rest_framework import serializers from .models import Book, Publish, Author, AuthorDetail class BookSerializer(serializers.ModelSerializer): class Meta: model = Book fields = ['id','title','price','publish','authors','publish_detail','author_detail'] # 欄位可是屬性,也可以是方法 # depth=1 # 深度查一層,官方建議不大於10,正常不超過3,不建議用 extra_kwargs={'publish':{'write_only':True}, 'author':{'write_only':True}, 'publish_detail':{'read_only':True}, 'author_detail':{'read_only':True} } # 只顯示publish的出版社名字和地址 # 方式一:在表模型中寫方法,在序列化類的fields宣告一下就可以
圖書的多表通過Postman關聯的序列化和反序列化
方法二:在序列化類中寫
serializer.py
from rest_framework import serializers from .models import Book, Publish, Author, AuthorDetail class BookSerializer(serializers.ModelSerializer): class Meta: model = Book # 寫在BookSerializer的類屬性,也需要在fields中註冊一下 fields = ['id', 'title', 'price', 'publish', 'authors','publish_detail','author_detail'] # 欄位可是屬性,也可以是方法 # depth=1 # 深度查一層,官方建議不大於10,正常不超過3,不建議用 extra_kwargs = {'publish': {'write_only': True}, 'author': {'write_only': True}, } # 只顯示publish的出版社名字和地址 # 方法二: 在序列化類中寫 publish_detail = serializers.SerializerMethodField(read_only=True) # 這欄位需要配合一個方法,方法必須叫get_欄位名,方法返回什麼,publish_detail def get_publish_detail(self, obj): # obj就是當前序列化到的物件,就是book物件 return {'name': obj.publish.name, 'address': obj.publish.address} author_detail=serializers.SerializerMethodField(read_only=True) def get_author_detail(self,obj): author_list = self.authors.all() author_dict_list = [] for author in author_list: author_dict_list.append({'name': author.name, 'sex': author.get_sex_display()}) return author_dict_list
圖書的多表通過Postman關聯的序列化和反序列化
方式三:通過子序列化
serializer.py
class BookSerializer(serializers.ModelSerializer): publish = PublishSerializer() authors = AuthorSerializer(many=True) # 多條,一定要加一個 many=True class Meta: model = Book # 寫在BookSerializer的類屬性,也需要在fields中註冊一下 fields = ['id', 'title', 'price', 'publish', 'authors'] # 欄位可以是屬性,也可以是方法(是方法返回值) # depth=1 # 深度查一層,官方建議不大於10,正常不超過3,不建議用 extra_kwargs = {'publish': {'write_only': True}, 'authors': {'write_only': True}, }