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关联的序列化和反序列化

 

 

posted @ 2021-12-22 21:45  甜甜de微笑  阅读(90)  评论(0编辑  收藏  举报