Django - 连接两个模型

7

我希望获取以下模型中,所有在指定时间段内transition_date字段有历史记录的设备:

class History(models.Model):
    device = models.ForeignKey(DeviceModel, to_field='id')
    transition_date = models.DateTimeField()

    class Meta:
        db_table = 'History'

class DeviceModel(models.Model):
    id = models.IntegerField()
    name = models.CharField()

    class Meta:
        db_table = 'Devices'

我有这样一段代码,可以筛选指定的时间间隔:
devices = DeviceModel.objects.filter(history__transition_date__range=(startDate, endDate))

这将给我与指定范围内的transition_date相对应的History表中的行数。过滤函数在device id上执行DeviceModelHistory之间的INNER JOIN,仅检索DeviceModel字段。我的问题是如何在连接设备ID时同时从HistoryDeviceModel中检索数据。我不想编写自定义SQL查询。

1个回答

12

在您的模型中,DeviceHistory 模型通过 History 到 DeviceModel 的外键相关联。这意味着当您有一个 History 对象时,您可以检索与其相关的 Device 模型,反之亦然(如果您有一个 Device,则可以获取其历史记录)。

例如:

first_history = History.objects.all()[0]
first_history.device  # This return the device object related with first_history
first_history.device.name # This return the name of the device related with first_history

但它也可以以另一种方式工作,你可以这样做:

first_device = Device.objects.all()[0]
first_device.history  # This return the history object related with device
first_device.history.transition_date  # Exactly as before, can access history fields

因此,在您的查询中:

devices = DeviceModel.objects.filter(history__transition_date__range=(startDate, endDate))
这会返回设备列表,但你可以访问与每个设备对象相关的历史记录。
对你来说这不够吗?你有一个设备列表,每个设备都可以访问其相关的历史记录对象。
信息:当声明一个外键字段时,默认情况下模型是通过id相关联的。我之所以这么说是因为你正在进行:
device = models.ForeignKey(DeviceModel, to_field='id')

你可以看到你正在使用to_field='id',但是这个关系通常默认就已经建立了。如果你执行下面的操作:

device = models.ForeignKey(DeviceModel)

你会得到相同的结果


(编辑) 使用 .values() 获取列表 [device.name, history.date]

要获取像你所说的 [device.name, history.date] 这样的列表,你可以使用 Django QuerySet 的 .values() 函数,官方文档在这里

你可以尝试以下代码:

devices = DeviceModel.objects.filter(history__transition_date__range=(startDate, endDate)).values('name','history__transition_date')  
# Notice that it is 'history _ _ transition_date with 2 underscores

我想将那些设备+每个设备的历史记录进行序列化,并将它们作为HttpResponse返回,但当我对它们进行序列化时,我只得到了这些设备。 - AlexandruC
将您想要查看的历史字段添加到您正在执行的查询中。 - AlvaroAV
你可以使用Django函数序列化查询,你需要什么作为Django查询的结果?你想如何序列化数据? - AlvaroAV
我想要一个包含 [device.name, history.transition date] 的列表。 - AlexandruC
尝试使用我在答案中添加的查询,它应该返回一个字典列表,如下所示:[{'history__transition_date':whatever, 'name':whatever},{'history__transition_date':whatever, 'name':whatever}, ...] - AlvaroAV

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接