当前位置: 首页 > news >正文

Django一分钟:DRF模型序列化器处理关联关系的示例与注意事项

DRF的ModelSerializer序列化器与Django的Model模型紧密映射,本文将通过简单的示例介绍几种处理关联关系的方法。

1. 创建模型和初始数据

创建模型

from django.db import modelsclass Product(models.Model):product_name = models.CharField(max_length=255)quantity = models.IntegerField()class Component(models.Model):product = models.ForeignKey(Product, on_delete=models.CASCADE, related_name='components')component_name = models.CharField(max_length=255)code = models.CharField(max_length=255)quantity = models.IntegerField()class Meta:ordering = ['product']def __str__(self):return f'{self.code}-{self.component_name}'

创建数据

>>> from api.models import Product, Component
>>> p1 = Product.objects.create(product_name="盖子", quantity=30)
>>> Component.objects.create(product=p1, component_name='纤维板', code='XYB', quantity=5)
>>> Component.objects.create(product=p1, component_name='螺丝', code='LS', quantity=10)
>>> Component.objects.create(product=p1, component_name='密封条', code='MFT', quantity=20)

2. 字符串关系字段

使用StringRelatedField

from rest_framework import serializers
from .models import Productclass ProductSerializer(serializers.ModelSerializer):components = serializers.StringRelatedField(many=True)class Meta:model = Productfields = ['product_name', 'quantity', 'components']

执行查询和序列化

>>> from api.models import Product
>>> p1 = Product.objects.prefetch_related('components').get(pk=1)
>>> from api.serializers import ProductSerializer
>>> ps = ProductSerializer(p1)
>>> ps.data
# {'product_name': '盖子', 'quantity': 30, 'components': ['XYB-纤维板', 'LS-螺丝', 'MFT-密封条']}

效果如下:

{'product_name': '盖子', 'quantity': 30, 'components': ['XYB-纤维板', 'LS-螺丝', 'MFT-密封条']
}

注意观察获取查询集的代码:Product.objects.prefetch_related('components').get(pk=1)不难发现我们使用了prefetch_related来获取查询集,如果一次查询大量的Product,不使用prefetch_related将会导致严重的性能问题(N+1问题)。DRF的序列化器不会为你自动优化。当然我们的示例中影响不大,因为只获取了一个查询集。

3. 主键关系字段

使用PrimaryKeyRelatedField

from rest_framework import serializers
from .models import Productclass ProductSerializer(serializers.ModelSerializer):components =  serializers.PrimaryKeyRelatedField(many=True, read_only=True)class Meta:model = Productfields = ['product_name', 'quantity', 'components']

效果如下:

{'product_name': '盖子', 'quantity': 30, 'components': [1, 2, 3]
}

4. 指定关系字段

使用SlugRelatedField可以指定字段来表示关联关系:

from rest_framework import serializers
from .models import Productclass ProductSerializer(serializers.ModelSerializer):components =  serializers.SlugRelatedField(many=True,read_only=True,slug_field='code')class Meta:model = Productfields = ['product_name', 'quantity', 'components']

效果如下:

{'product_name': '盖子', 'quantity': 30, 'components': ['XYB', 'LS', 'MFT']
}

5. 嵌套序列化器

from rest_framework import serializers
from .models import Product, Componentclass ComponentSerializer(serializers.ModelSerializer):class Meta:model = Componentfields = ['component_name', 'code', 'quantity']class ProductSerializer(serializers.ModelSerializer):components =  ComponentSerializer(many=True, read_only=True)class Meta:model = Productfields = ['product_name', 'quantity', 'components']

效果如下:

{"product_name": "盖子","quantity": 30,"components": [{"component_name": "纤维板","code": "XYB","quantity": 5},{"component_name": "螺丝","code": "LS","quantity": 10},{"component_name": "密封条","code": "MFT","quantity": 20}]
}

6. 可写嵌套

默认上面创建的嵌套序列化器是只读的,可写嵌套需要实现updatecreate两者或其一:

from rest_framework import serializers
from .models import Product, Componentclass ComponentSerializer(serializers.ModelSerializer):class Meta:model = Componentfields = ['component_name', 'code', 'quantity']class ProductSerializer(serializers.ModelSerializer):components =  ComponentSerializer(many=True)class Meta:model = Productfields = ['product_name', 'quantity', 'components']def create(self, validated_data):components_data = validated_data.pop('components')product = Product.objects.create(**validated_data)for component_data in components_data:Component.objects.create(product=product, **component_data)return product

可以使用此序列化器创建实例:

>>> data = {"product_name": "电机","quantity": 1,"components": [{"component_name": "铝型材","code": "LXC","quantity": 5},{"component_name": "螺栓","code": "LSHUN","quantity": 10},]
}
>>> from api.serializers import ProductSerializer
>>> s = ProductSerializer(data=data)
>>> s.is_valid()
# True
>>> s.save()
# <Product: Product object (2)>

7. 总结注意事项

  1. 关联关系注意使用prefetch_related获取查询集。
  2. 可写嵌套序列化器必须自己实现create方法update方法两者或其一。
http://www.lryc.cn/news/450701.html

相关文章:

  • Python爬虫selenium框架基本使用
  • sql 时间交集
  • 【深度学习】05-Rnn循环神经网络-01- 自然语言处理概述/词嵌入层/循环网络/文本生成案例精讲
  • 基于JAVA+SpringBoot+Vue的电商平台的设计与实现
  • CSS盒模型-怪异盒模型笔记-思维导图-案例等
  • thinkphp6开发的通用网站系统源码
  • Junit 5 - 理解Mockito,提高UT 覆盖率
  • 微服务sentinel解析部署使用全流程
  • YOLO11震撼发布!
  • 机器学习框架(含实例说明)
  • vue2与vue3知识点
  • 从源码中学习动态代理模式
  • 谷歌浏览器完美清除缓存
  • 《如何高效学习》
  • 阿里云ACP认证考试题库
  • 学习经验分享【38】YOLOv11解读——最新YOLO版本
  • 电商选品/分析| 亚马逊常见插件爬虫实战之-helium插件
  • 遇到慢SQL、SQL报错,应如何快速定位问题 | OceanBase优化实践
  • postgresql僵尸进程的处理思路
  • Springboot 练习
  • ISA-95制造业中企业和控制系统的集成的国际标准-(3)
  • MATLAB中图形导出功能的详细使用指南
  • 助农小程序|助农扶贫系统|基于java的助农扶贫系统小程序设计与实现(源码+数据库+文档)
  • SpringBoot上传图片实现本地存储以及实现直接上传阿里云OSS
  • git clone或repo init 时报错:fatal: 协议错误:错误的行长度 xxx
  • SpringBoot2(Spring Boot 的Web开发 springMVC 请求处理 参数绑定 常用注解 数据传递 文件上传)
  • 成都网安周暨CCS2024 | 大模型安全与产业应用创新研讨活动成功举办
  • React 解释常见的 hooks: useState / useRef / useContext / useReducer
  • telnet发送邮件教程:安全配置与操作指南?
  • 超强大的 Nginx 可视化管理工具