You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django ORM外键集合查询:筛选指定日期全可用的房间

Django ORM 查询符合条件的 Room

首先修正模型代码中的拼写错误(否则无法正常运行):

class Room(models.Model):
    name = models.CharField(max_length=64)  # 修正 Charfield -> CharField,max_lentgh -> max_length

class Availability(models.Model):
    date = models.DateField()
    closed = models.BooleanField(default=False)
    room = models.ForeignKey(Room, on_delete=models.CASCADE)  # Django 3.0+ 建议必填 on_delete 参数

针对你的需求,可通过以下步骤实现查询:

假设你要查询的日期范围是 start_date 到 end_date(比如连续7天),先计算该范围的总天数:

from datetime import date
from django.db.models import Count, Q

start_date = date(2024, 5, 1)
end_date = date(2024, 5, 7)
days_count = (end_date - start_date).days + 1  # 计算日期范围总天数,包含首尾两天

方式一:结合 annotate 和 filter 实现

available_rooms = Room.objects.annotate(
    # 统计当前 Room 在指定日期范围内的 Availability 记录数
    valid_availability_count=Count(
        'availability',
        filter=Q(availability__date__range=(start_date, end_date))
    )
).filter(
    # 条件1:记录数等于日期范围总天数,确保每天都有对应的 Availability 记录
    valid_availability_count=days_count,
    # 条件2:日期范围内所有 Availability 的 closed 均不为 True
    availability__date__range=(start_date, end_date),
    availability__closed=False
).distinct()  # 去重,避免因关联多条 Availability 导致 Room 重复

方式二:用 exclude 排除不符合条件的 Room

逻辑更直观:先筛选出日期范围记录完整的 Room,再排除其中存在 closed=True 的 Room

available_rooms = Room.objects.annotate(
    valid_availability_count=Count(
        'availability',
        filter=Q(availability__date__range=(start_date, end_date))
    )
).filter(
    valid_availability_count=days_count
).exclude(
    # 排除日期范围内存在 closed=True 的 Room
    availability__date__range=(start_date, end_date),
    availability__closed=True
)

逻辑说明

  1. 检查日期范围记录完整性:通过 annotate + Count 统计每个 Room 在指定日期内的 Availability 数量,当数量等于日期范围总天数时,说明该 Room 在这段时间的每天都有对应的记录。
  2. 确保所有 closed 不为 True:要么通过 filter 直接限定关联的 Availability 满足 closed=False,要么通过 exclude 排除存在 closed=True 的 Room,两种方式都能实现需求。

内容的提问来源于stack exchange,提问作者Kihaf

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 14:45:41