drf之多表关联反序列化保存read_only与write_only

发布时间 2023-04-21 17:39:43作者: 树苗叶子


假如前端传入了一组数据:
{name:'赛尔达传说:王国之泪', price: 350, publish: 1, authors: [1, 2]}
如上: publish按id传入,authors也按id传入。

read_only与write_only

  • read_only用于序列化
  • write_only用于反序列化
  • 这两个是字段参数

示例

# 要新增的数据:
{'name': '恶魔之魂', 'price': '360', 'publish': '1', 'authors': [3, 4]}

models.py

from django.db import models


# Create your models here.
class Book(models.Model):
    name = models.CharField(max_length=32)
    price = models.CharField(max_length=32)
    # 图书与出版社外键字段,一对多
    publish = models.ForeignKey(to='Publish', on_delete=models.CASCADE)
    # 图书与作者外键字段,多对多
    authors = models.ManyToManyField(to='Author')

    # 在模型表中定制序列化类
    @property
    def publish_detail(self):  # 定义的名字需要与serializer.py中定义的序列化类中的名字相同
        return {'name': self.publish.name, 'addr': self.publish.addr}

    @property
    def authors_detail(self):  # 定义的名字需要与serializer.py中定义的序列化类中的名字相同
        list = []
        for author in self.authors.all():
            list.append({'name': author.name, 'phone': author.phone})
        return list


class Publish(models.Model):
    name = models.CharField(max_length=32)
    addr = models.CharField(max_length=64)


class Author(models.Model):
    name = models.CharField(max_length=32)
    phone = models.CharField(max_length=11)

serializer.py

from rest_framework import serializers
from app01 import models


class BookSerializers(serializers.Serializer):
    # 不指定read_only与write_only则表示可以用来读也可以用来写
    name = serializers.CharField()
    price = serializers.CharField()

    # 指定read_only表示只用来读,也就是序列化
    publish_detail = serializers.DictField(read_only=True)
    authors_detail = serializers.ListField(read_only=True)

    # 指定write_only表示只用来写,也就是反序列化
    publish = serializers.CharField(write_only=True)
    authors = serializers.ListField(write_only=True)

    # 新增就需要重写create方法
    def create(self, validated_data):
        # validated_data是字典类型{'name': '恶魔之魂', 'price': '360', 'publish': '1', 'authors': [3, 4]}
        book = models.Book.objects.create(name=validated_data.get('name'),
                                          price=validated_data.get('price'),
                                          publish_id=validated_data.get('publish'))
        # 反序列化保存多对多关系表
        book.authors.add(*validated_data.get('authors'))
        return book

views.py

from rest_framework.response import Response
from rest_framework.views import APIView
from app01 import models
from app01.serializer.serializer import BookSerializers


class BookView(APIView):
    def get(self, request):
        book_obj = models.Book.objects.all()
        book_ser = BookSerializers(instance=book_obj, many=True)
        return Response(book_ser.data)

    def post(self, request):
        book_ser = BookSerializers(data=request.data)
        if book_ser.is_valid():
            book_ser.save()
            return Response({'code': 100, 'msg': '新增成功'})
        else:
            return Response({'code': 101, 'msg': book_ser.errors})