11 多表关联的序列化和反序列化
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}, }
注意:其他的几个文件都不变
图书的多表通过Postman关联的序列化和反序列化