如何在Django中遍历Thermocouple模型创建TemperatureRecord数据表
问题背景
已实现Thermocouple模型用于管理热电偶,需要创建TemperatureRecord模型,为每个已存在的热电偶记录温度数据并存储到数据库。
现有数据
Thermocouple表数据
| Id | name |
|---|---|
| 1 | thermocouple_1 |
| 2 | thermocouple_2 |
| 3 | thermocouple_3 |
期望的TemperatureRecord表结构
| id | date | time | user | thermocouple_1 | thermocouple_2 | thermocouple_3 |
|---|---|---|---|---|---|---|
| 1 | 2024-03-05 | 14:48 | 1 | 温度值1 | 温度值2 | 温度值3 |
| 2 | 2024-03-05 | 14:52 | 2 | 温度值1 | 温度值2 | 温度值3 |
| 3 | 2024-03-05 | 14:55 | 1 | 温度值1 | 温度值2 | 温度值3 |
现有Thermocouple模型代码
class Thermocouple(models.Model): name = models.CharField(max_length=50, unique=True, help_text="Name of the thermocouple") def __str__(self): return f"{self.name}" class Meta: ordering = ['id'] @classmethod def bulk_create_from_import(cls, data): cls.objects.bulk_create([cls(**item) for item in data])
尝试的无效代码
尝试在__init__方法中动态添加温度字段,但未生效:
class TemperatureRecord(models.Model): date = models.DateField() time = models.TimeField() user = models.ForeignKey(User, on_delete=models.CASCADE) def __init__(self, *args, **kwargs): super(TemperatureRecord, self).__init__(*args, **kwargs) temperatures = Thermocouple.objects.all() for thermocouple in temperatures: field_name = thermocouple.name.lower().replace(" ", "_") # 创建对应热电偶的字段名 setattr(self, field_name, models.IntegerField(null=True, blank=True))
问题原因
在模型的__init__方法中动态添加字段是无效的,因为Django的模型字段是在类定义阶段注册到模型元数据中的,实例化时添加的字段不会被数据库识别,也无法生成对应的表结构。
解决方案
方案1:动态生成模型字段(适合固定数量的热电偶)
在TemperatureRecord类定义完成后,遍历已有的Thermocouple实例,动态为模型添加对应的温度字段。注意:后续新增热电偶需要重新执行迁移命令更新表结构。
from django.db import models from django.contrib.auth.models import User from .models import Thermocouple class TemperatureRecord(models.Model): date = models.DateField() time = models.TimeField() user = models.ForeignKey(User, on_delete=models.CASCADE) def __str__(self): return f"记录 {self.id} - {self.date} {self.time}" # 动态添加每个热电偶对应的温度字段 for thermocouple in Thermocouple.objects.all(): field_name = thermocouple.name.lower().replace(" ", "_") # 使用add_to_class方法为模型添加字段 TemperatureRecord.add_to_class( field_name, models.IntegerField(null=True, blank=True, verbose_name=f"{thermocouple.name} 温度") )
注意事项
- 首次运行前需确保
Thermocouple表已创建并存在数据,否则不会生成任何温度字段 - 新增热电偶后,需重新运行代码并执行
python manage.py makemigrations和python manage.py migrate更新数据库 - 此方案适合热电偶数量固定或极少变化的场景
方案2:关联模型设计(推荐,支持动态增减热电偶)
如果热电偶数量会动态变化,宽表结构会导致频繁修改表结构,推荐使用一对多的关联模型,将每个热电偶的温度读数作为独立记录存储:
class TemperatureRecord(models.Model): date = models.DateField() time = models.TimeField() user = models.ForeignKey(User, on_delete=models.CASCADE) def __str__(self): return f"记录 {self.id} - {self.date} {self.time}" class TemperatureReading(models.Model): record = models.ForeignKey(TemperatureRecord, on_delete=models.CASCADE, related_name="readings") thermocouple = models.ForeignKey(Thermocouple, on_delete=models.CASCADE) temperature = models.IntegerField(null=True, blank=True) class Meta: unique_together = ('record', 'thermocouple') # 确保同一记录中每个热电偶仅存一个读数 def __str__(self): return f"{self.thermocouple.name}: {self.temperature}"
优势
- 新增/删除热电偶无需修改表结构,直接操作
Thermocouple模型即可 - 数据结构更灵活,可轻松扩展温度单位、读数精度等字段
- 查询时通过
record.readings.all()即可获取该记录下所有热电偶的读数
内容的提问来源于stack exchange,提问作者Aashutosh Shrestha
相关产品推荐
相关产品推荐

