32.关系字段的序列化
很多时候我们的模型设计并不只是单一的字段数据,还有多对多、1对多、关联等
序列化与单一的字段数据有所不同
模型类
'''
如下三个模型类
Text分别与auth和category外键关联和多对多关联
'''
# 作者
class Auth(models.Model):
username = models.CharField(max_length=130)
# 分类
class Category(models.Model):
name = models.CharField(max_length=130)
# 文章
class Text(models.Model):
title = models.CharField(max_length=130)
content = models.TextField()
'''
定义外键关联和多对多
'''
auth = models.ForeignKey(Auth, on_delete=models.CASCADE)
category = models.ManyToManyField(Category, blank=True)
class Meta:
ordering = ['created']
序列化器
from rest_framework import serializers
from .models import Auth, Category, Text
# 作者
class AuthSerializer(serializers.ModelSerializer):
class Meta:
model = Auth
fields = ('id', 'username',)
# 分类
class CategorySerializer(serializers.ModelSerializer):
class Meta:
model = Category
fields = ('id', 'username',)
# 文本
class TextSerializer(serializers.ModelSerializer):
class Meta:
model = Text
fields = ('id', 'title', 'content', 'auth', 'category')
视图
from .models import Auth, Text, Category
from .serializer import AuthSerializer, TextSerializer, CategorySerializer
from rest_framework.viewsets import ModelViewSet
class AuthViewSet(ModelViewSet):
queryset = Auth.objects.all()
serializer_class = AuthSerializer
class CategoryViewSet(ModelViewSet):
queryset = Category.objects.all()
serializer_class = CategorySerializer
class TextViewSet(ModelViewSet):
queryset = Text.objects.all()
serializer_class = TextSerializer
路由
from . import views
from rest_framework.routers import DefaultRouter
router = DefaultRouter()
router.register(r'auth', views.AuthViewSet,basename='auth')
router.register(r'category', views.Category,basename='category')
router.register(r'text', views.Text,'text')
urlpatterns = router.urls
字段处理
遵循restful规范,一个名词url只处理一个资源,就像上面代码
不在嵌套的关系字段中同时创建对象
比如创建auth,我们用auth去处理,而不是创建text对象同时创建可auth
前后端协商接口的时候,就要将逻辑分开
# 如果非要在Text中去对auth、category去做处理,这种设计不主张,但是也可以实现
class TextSerializer(serializers.ModelSerializer):
# 在text序列化类中声明auth的序列化类
# 有auth的处理,会使用AuthSerializer进行
# 在序列化中的实例,本身也是一种字段
# 如果不声明直接就使用text对auth进行操作,会请求出错
auth = AuthSerializer()
class Meta:
model = Text
fields = ('id', 'title', 'content', 'auth', 'category','created')
# 声明atuh序列化类之后直接请求会抛出non_field_error
# 在反向序列化的时候,源码默认的create方法不支持嵌套的字段
# 所以需要我们重写create方法
'''
请求的validated_data 数据:
{'title': 'python', 'content': 'test', 'auth': OrderedDict([('username', '嵌套用户请求')])}
可以看出auth是的数据是嵌套在对应层级内
'''
def create(self, validated_data):
auth_data = validated_data.pop('auth') # 通过pop拿出auth对应的值
# 我们要把对应内容创建给Auth,需要调用对应模型的创建
# 有就获取用户,如果没有就创建用户,get_or_create除了返回结果还会返回对应状态 True /False
auth,flag = Auth.objects.get_or_create(username=auth_data['username'])
# 上面我们通过pop把auth拿出来单独传入,其他的字典数据解包传入
text = Text.objects.create(auth=auth, **validated_data)
return text
'''
上面create只处理了关联的user外键,
如果处理category的多对多字段,还需要单独处理
'''
def create(self, validated_data):
# 在text处理关联的多对多字段是跟外键一样的嵌套关系
category_data = [] # 定义一个多对多空列表
if validated_data['category']: # 如果有传入多对多字段数据
category_data = validated_data.pop('category') # 将对应数据拿出
auth_data = validated_data.pop('auth')
auth = Auth.objects.get_or_create(username=auth_data['username'])
text = Text.objects.create(auth=auth, **validated_data)
# 待其他数据处理完毕之后判断是否有传入多对多字段
if category_data:
# text关联的category使用add方法进行字段追加
# add 就是orm针对多对多处理的语法
text.category.add(*category_data)
return text
# 更新数据重写update方法
def update(self, instance, validated_data):
category_data = validated_data.pop('category')
auth_data = validated_data.pop('auth')
# 如果多对多字段 category有值
if category_data:
# 更新对应的值
instance.category.set(category_data)
# 先更新没有关联外键、多对多关联的数据
instance.title = validated_data.get('title', instance.title)
instance.title = validated_data.get('content', instance.content)
instance.created = validated_data.get('created', instance.created)
instance.id = validated_data.get('id', instance.id)
instance.content = validated_data.get('content', instance.content)
# auth 外键更新
auth = instance.auth # 获取到auth 模型
auth.username = auth_data.get('username', auth.username)
auth.save()
return instance
风月都好看,人间也浪漫.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)