【问题标题】:Django - join two modelsDjango - 加入两个模型
【发布时间】:2014-09-17 12:19:09
【问题描述】:

对于以下模型,我想检索在历史表中具有指定间隔之间的 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))

这给了我与History 表在指定范围内的transition_date 一样多的行。 过滤器函数在device id 上执行DeviceModelHistory 之间的INNER JOIN,仅检索DeviceModel 字段。我的问题是如何同时从HistoryDeviceModel 检索数据,同时将它们与设备ID 上的filter/select_related 一起加入。 我宁愿不编写自定义 SQL 查询。

【问题讨论】:

    标签: django django-models


    【解决方案1】:

    在您的模型中,DeviceHistory 模型与从 History 到 DeviceModel 的外键相关,这意味着当您拥有 History 对象时,您可以检索与 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))
    

    这会返回一个设备列表,但您可以访问与每个设备对象相关的历史记录

    这还不够吗?你有一个设备列表,每个设备都可以访问其相关的历史对象

    信息:当您声明一个 ForeignKey 字段时,模型默认通过 id 关联,我这样说是因为您正在这样做:

    device = models.ForeignKey(DeviceModel, to_field='id')
    

    如您所见,您使用的是to_field='id',但如果您这样做,则默认情况下会完成此关系:

    device = models.ForeignKey(DeviceModel)
    

    你会得到相同的结果


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

    要得到你说的[device.name, history.date]的列表,你可以使用Django QuerySet的.values()函数,官方文档here

    你可以试试这样的:

    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 返回,当我序列化它们时我只得到设备。
    • 将要查看的历史字段添加到正在执行的查询中
    • 您可以使用 django 函数序列化您的查询,您需要什么作为 django 查询的结果?你想如何序列化数据?
    • 我想要一个 [device.name, history.transition date] 的列表
    • 尝试使用我在答案中添加的查询,它应该返回一个字典列表,例如:[{'history__transition_date':whatever, 'name':whatever},{'history__transition_date':whatever, 'name':whatever}, ...]
    猜你喜欢
    • 1970-01-01
    • 2016-08-13
    • 2020-05-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-19
    • 2015-03-10
    相关资源
    最近更新 更多