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())
]
分类:
python相关 / drf
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· AI与.NET技术实操系列(六):基于图像分类模型对图像进行分类