You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django QuerySet中如何获取ForeignKey名称而非主键值

解决Django QuerySet返回关联对象sensor_name的问题

我正在构建一个复杂的Django QuerySet,需要返回ForeignKey关联的TreeSensor的sensor_name而非主键ID。通过AJAX获取用户输入的实时数据并在DataTable中展示,但当前返回的JSON数据里只有sensor的主键,没有sensor_name。

模型代码

class TreeSensor(models.Model):

    class Meta:
        verbose_name_plural = "Tree Sensors"

    field = models.ForeignKey(Field, on_delete=models.CASCADE)
    sensor_name = models.CharField(max_length=200, blank=True)
    datetime = models.DateTimeField(blank=True, null=True, default=now)
    longitude = models.DecimalField(max_digits=22, decimal_places=16, blank=True, null=True)
    latitude = models.DecimalField(max_digits=22, decimal_places=16, blank=True, null=True)

class TreeSensorMeasurement(models.Model):

    class Meta:
        verbose_name_plural = "Tree Sensor Measurements"

    sensor = models.ForeignKey(TreeSensor, on_delete=models.CASCADE)
    datetime = models.DateTimeField(blank=True, null=True, default=None)

    soil_moisture_depth_1 = models.DecimalField(max_digits=15, decimal_places=2)
    soil_moisture_depth_2 = models.DecimalField(max_digits=15, decimal_places=2)
    soil_moisture_depth_1_filtered = models.DecimalField(max_digits=15, decimal_places=2, blank=True, null=True)
    soil_moisture_depth_2_filtered = models.DecimalField(max_digits=15, decimal_places=2, blank=True, null=True)
    soil_temperature = models.DecimalField(max_digits=15, decimal_places=2)

视图代码(省略非关键部分)

field_list = Field.objects.filter(user=request.user)   
tree_sensors = TreeSensor.objects.filter(field_id__in=field_list.values_list('id', flat=True))   
statSensors = (TreeSensorMeasurement.objects
              .filter(sensor_id__in=tree_sensors.values_list('id', flat=True))                                
              .filter(datetime__date__lte=To_T[0]).filter(datetime__date__gte=From_T[0])                       
              .filter(soil_moisture_depth_1__lte=To_T[1]).filter(soil_moisture_depth_1__gte=From_T[1]) 
              .filter(soil_moisture_depth_2__lte=To_T[2]).filter(soil_moisture_depth_2__gte=From_T[2])    
              .filter(soil_temperature__lte=To_T[3]).filter(soil_temperature__gte=From_T[3])                   
              .order_by('sensor', 'datetime'))
TreeData = serializers.serialize('json', statSensors)

前端收到的示例数据

{
  "datetime": "2022-11-20T13:28:45.901Z",
  "sensor": 2,
  "soil_moisture_depth_1": "166.00",
  "soil_moisture_depth_1_filtered": "31.00",
  "soil_moisture_depth_2": "171.00",
  "soil_moisture_depth_2_filtered": "197.00",
  "soil_temperature": "11.00"
}

解决方案

方法1:使用values()指定字段(简单直接)

修改QuerySet,用values()明确包含需要的字段,包括关联对象的sensor__sensor_name,同时可通过annotate重命名字段:

from django.db.models import F
import json

statSensors = (TreeSensorMeasurement.objects
              .select_related('sensor')  # 预加载关联对象,避免N+1查询
              .filter(sensor_id__in=tree_sensors.values_list('id', flat=True))                                
              .filter(datetime__date__lte=To_T[0]).filter(datetime__date__gte=From_T[0])                       
              .filter(soil_moisture_depth_1__lte=To_T[1]).filter(soil_moisture_depth_1__gte=From_T[1]) 
              .filter(soil_moisture_depth_2__lte=To_T[2]).filter(soil_moisture_depth_2__gte=From_T[2])    
              .filter(soil_temperature__lte=To_T[3]).filter(soil_temperature__gte=From_T[3])                   
              .order_by('sensor', 'datetime')
              .annotate(sensor_name=F('sensor__sensor_name'))
              .values(
                  'datetime', 
                  'soil_moisture_depth_1', 'soil_moisture_depth_1_filtered',
                  'soil_moisture_depth_2', 'soil_moisture_depth_2_filtered',
                  'soil_temperature',
                  'sensor_name'
              ))

TreeData = json.dumps(list(statSensors))

方法2:自定义序列化逻辑(灵活可控)

如果需要保留模型对象结构,可手动构造返回数据:

import json

def serialize_measurements(measurements):
    data = []
    for obj in measurements:
        item = {
            'datetime': obj.datetime.isoformat(),
            'sensor': obj.sensor.id,
            'sensor_name': obj.sensor.sensor_name,
            'soil_moisture_depth_1': str(obj.soil_moisture_depth_1),
            'soil_moisture_depth_1_filtered': str(obj.soil_moisture_depth_1_filtered) if obj.soil_moisture_depth_1_filtered else None,
            'soil_moisture_depth_2': str(obj.soil_moisture_depth_2),
            'soil_moisture_depth_2_filtered': str(obj.soil_moisture_depth_2_filtered) if obj.soil_moisture_depth_2_filtered else None,
            'soil_temperature': str(obj.soil_temperature)
        }
        data.append(item)
    return json.dumps(data)

# 预加载关联对象优化性能
statSensors = statSensors.select_related('sensor')
TreeData = serialize_measurements(statSensors)

内容的提问来源于stack exchange,提问作者user20585556

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 16:15:44