如何通过相关对象查询模型并使用Django ORM在queryset中获取相关对象

时间:2018-09-03 23:54:20

标签: python django django-models django-orm

我知道可以使用Django ORM使用反向相关字段来查询模型。但是是否也可以获取查询匹配的反向相关模型的所有字段?

例如,如果我们具有以下模型:

class Location(models.Model):
    name = models.CharField(max_length=50)


class Availability(models.Model):
    location = models.ForeignKey(Location, on_delete=models.CASCADE)

    start_datetime = models.DateTimeField()
    end_datetime = models.DateTimeField()

    price = models.PositiveIntegerField()

是否有可能找到特定时间范围内所有可用的Location,并在该可用性期间获得price中的Location?我们假设Availability个具有相同位置的对象不能具有重叠的开始/结束日期时间。

如果用户输入了user_start_datetimeuser_end_datetime,则我们可以执行以下操作:

Location.objects.filter(
    availability__start_datetime__lte=start_datetime,
    availability__end_datetime__gte=end_datetime)

但是我不确定如何也获取特定price的{​​{1}}字段,该字段确实导致查询匹配。

在原始SQL中,我正在谈论的行为可以通过以下方式实现:

availability

我曾考虑使用类似SELECT l.id, l.name, a.price FROM Location l INNER JOIN Availability a ON a.location_id = l.id WHERE /* availability is within user-inputted timeframe */ 的东西,但这只会给我 all 所有与查询匹配的prefetch_related('availability_set')对象的可用性。我只想要在查询的时间范围内的一个 Location,更具体地说,就是那个availability的{​​{1}}。

1 个答案:

答案 0 :(得分:2)

使用ORM时,通常一次一次从一个模型类中获取结果。由于LocationAvailability是独立的模型,因此您只需执行以下操作即可:

availabilities = Availability.objects.filter(
    start_datetime__lte=start_datetime,
    end_datetime__gte=end_datetime)
for availability in availabilities:
    print(availability.location.id, availability.location.name, availability.price)

这是一个易于阅读的实现。

现在,从Location对象(在Availability中访问availability.location需要第二个SQL查询。您可以使用select_related对此进行优化:

  

这是一个性能提升器,它导致一个更复杂的查询,但意味着以后使用外键关系将不需要数据库查询。

只需将其附加到您的原始查询中,即:

availabilities = Availability.objects.select_related('location').filter(...

这将在后台创建一个SQL连接语句,Location对象将不需要额外的查询。