Django - 加入两个模型

Ale*_*ruC 6 django django-models

对于以下模型,我想检索历史表中具有条目的所有设备,其中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'
Run Code Online (Sandbox Code Playgroud)

我有这个代码过滤指定的间隔:

devices = DeviceModel.objects.filter(history__transition_date__range=(startDate, endDate))
Run Code Online (Sandbox Code Playgroud)

这给了我在Historytransition_date中指定范围内的行数.滤波器函数进行内之间JOIN DeviceModelHistorydevice id仅检索DeviceModel字段.我的问题是我如何检索两个数据History,并DeviceModel在同一时间,同时加入他们与过滤器/ select_related的设备ID.我宁愿不写自定义SQL查询.

Alv*_*oAV 9

在您的模型中,设备历史模型与从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
Run Code Online (Sandbox Code Playgroud)

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

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
Run Code Online (Sandbox Code Playgroud)

所以在你的查询中:

devices = DeviceModel.objects.filter(history__transition_date__range=(startDate, endDate))
Run Code Online (Sandbox Code Playgroud)

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

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

信息:当你声明一个ForeignKey字段时,模型与id默认相关,我说这是因为你正在做:

device = models.ForeignKey(DeviceModel, to_field='id')
Run Code Online (Sandbox Code Playgroud)

你可以看到你正在使用to_field='id'但是这个关系默认完成,如果你这样做:

device = models.ForeignKey(DeviceModel)
Run Code Online (Sandbox Code Playgroud)

你会得到相同的结果


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

要获得像你所说的列表[device.name, history.date]你可以使用.values()Django QuerySet的功能,这里是官方文档

您可以尝试以下方式:

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
Run Code Online (Sandbox Code Playgroud)