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


假如前端传入了一组数据:
{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})

修改示例

  • serializer.py
from rest_framework import serializers
from app01 import models


class BookSerializer(serializers.Serializer):
    name = serializers.CharField()
    price = serializers.CharField()

    # 定义write_only
    publish = serializers.CharField(write_only=True)
    authors = serializers.ListField(write_only=True)

    def update(self, instance, validated_data):
        # instance是要修改的对象
        instance.name = validated_data.get('name')
        instance.price = validated_data.get('price')
        instance.publish_id = validated_data.get('publish')
        authors = validated_data.get('authors')
        instance.authors.clear()  # 先清空关联关系
        instance.authors.add(*authors)
        # 保存instance
        instance.save()
        return instance
  • views.py
from app01 import models
from app01.serializer.serializer import BookSerializer
from rest_framework.views import APIView
from rest_framework.response import Response

class BookViewUpdate(APIView):
    # 修改的接口需要定义put方法
    def put(self, request, pk):
        # 根据前端传入的数据进行接收
        book_obj = models.Book.objects.filter(pk=pk).first()
        # 使用序列化类对数据进行序列化,instance就是要被序列化的对象
        book_ser = BookSerializer(data=request.data, instance=book_obj)
        # 对数据进行校验
        if book_ser.is_valid():
            # 校验通过,则将后台传过来的instance进行保存
            book_ser.save()
            return Response({'code': 100, 'msg': '新增成功'})
        else:
            return Response({'code': 101, 'msg': book_ser.errors})
  • urls.py
urlpatterns = [
    # 新增修改一个的接口,因为需要指定PK,所以在传入的时候需要把主键传入
    path('book/<int:pk>/', views.BookViewUpdate.as_view())
]
posted @   树苗叶子  阅读(108)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· AI与.NET技术实操系列(六):基于图像分类模型对图像进行分类
点击右上角即可分享
微信分享提示