我们如何在Django中查询反向外键属性?

时间:2014-05-28 14:23:45

标签: django postgresql django-queryset

我们正在使用带有PostgreSQL的Django 1.4.12为酒店建立一个网站。我们有酒店,每个酒店我们都有房间,每个房间都有客人(客人有一个房间的外键和一个房间到酒店)。在客人退房后,他的departure_date设置为现在,如果他在房间,则为空。我想选择有客人的房间和没有客人的房间,但我不能使用“guests__isnull”,因为客人退房后仍保持与房间相连。当客人的名字包含关键字时,我还需要搜索房间,但前提是他们在房间里。如果房间里至少有一位客人姓名匹配,我希望选择房间。但如果这位客人退房,则无法选择房间。

直到几天前,我们在退房后取消了客人的房间,但我们需要保留它以保存历史记录。我们的代码是这样的:

hotel.rooms.filter(
    Q(description__icontains=keyword) | 
    Q(identifier__icontains=keyword) | 
    (Q(guests__isnull=False) & Q(guests__name__icontains=keyword))
).distinct()

对于已入住的客房,我们添加了.exclude(guests__isnull=True)。但现在我们保留了房间,我们需要检查departure_date是否为空。我们现在怎么做?请记住,我们需要将关键字与会议室中的客人匹配,而不是与不在会议室中的客人匹配。我们还需要计算有客人的房间总数和没有客人的房间总数。

更新:我尝试使用以下查询计算有来宾的客房数量:

hotel.rooms.filter(guests__isnull=False, guests__departure_date__isnull=True).count()

但它返回的数字不正确(14而不是10)。你知道如何修复查询吗?

顺便说一下,这个查询返回没有客人(9个房间)的正确房间数:

hotel.rooms.exclude(guests__isnull=False, guests__departure_date__isnull=True).count()

为什么排除正确且过滤器不正确?

1 个答案:

答案 0 :(得分:1)

好的,我找到了解决方案。看来,使用过滤器(...),房间是按房间内的客人数量复制的,但是排除它们不是。有2种可能的解决方案来计算有客人的房间数量:

hotel.rooms.filter(guests__isnull=False, guests__departure_date__isnull=True).distinct().count()

或:

hotel.rooms.exclude(~Q(guests__isnull=False, guests__departure_date__isnull=True)).distinct().count()

计算没有客人的客房数量:

hotel.rooms.exclude(guests__isnull=False, guests__departure_date__isnull=True).distinct().count()

或:

hotel.rooms.exclude(Q(guests__isnull=False, guests__departure_date__isnull=True)).distinct().count()

搜索房间:

hotel.rooms.filter(
    Q(description__icontains=keyword) |
    Q(identifier__icontains=keyword) |
    Q(guests__isnull=False, guests__departure_date__isnull=True, guests__name__icontains=keyword)
).distinct()