复杂的查询集,带有不同模型的注释

时间:2014-04-19 14:45:34

标签: django django-queryset django-managers

我正在使用Django 1.6并拥有以下模型(为了便于阅读而略微简化):

class Person(models.Model):
    name = models.CharField(max_length=128)

class Room(models.Model):
    max_persons = models.SmallIntegerField()
    name = models.CharField(max_length=30, unique=True)

class Stay(models.Model):
    person = models.ForeignKey(Person)
    STAY_TYPE = (
        (1, 'Type 1'),
        (2, 'Type 2'),
        (3, 'Type 3'),
    )
    stay_type = models.CharField(max_length=1, choices=STAY_TYPE)

class Hospitalization(models.Model):
    stay = models.ForeignKey(Stay)
    date_in = models.DateField()
    date_out = models.DateField(blank=True, null=True)
    room = models.ForeignKey(Room)

使用queryset(在经理中),我想获得给定日期的所有可用房间,即max_persons未满足的地方。

到目前为止,我已尝试使用Q以及Room.objects.filter(hospitalization__date_out__lt="2014-04-25")之类的内容,但我无法找出max_persons比较。

你有什么想法吗?

修改

与每个房间相关的人物对象的数量代表该房间的人数。

因此,根据卡尔的建议,我试图玩弄:

  • Room.objects.filter(hospitalization__date_out__lte="2014-04-25").annotate(num_persons=hospitalization_set__stay__person.Count()).exclude(num_persons__lte=max_persons)
    • 收益率NameError: name 'hospitalization_set__stay__person' is not defined
  • Room.objects.filter(hospitalization__date_out__lte="2014-04-25").annotate(num_persons=Count('hospitalization_set__stay__person')).exclude(num_persons__lte=max_persons)
    • 收益率FieldError: Cannot resolve keyword 'hospitalization_set' into field.
  • Room.objects.filter(hospitalization__date_out__lte="2014-04-25").annotate(num_persons=Count('hospitalization__stay__person')).exclude(num_persons__lte=F('max_persons'))
    • 没有任何收益([]),而根据我目前的数据库,我预计至少会有三个结果。
    • 删除.exclude()时,我仍然没有结果。看起来我使用.annotate()做错了。

1 个答案:

答案 0 :(得分:1)

我相信与Room.objects.filter(hospitalization__date_out="2014-04-25", max_persons__lt=x)类似的东西应该可以解决问题。请记住,您可以在过滤器操作中具有多个声明,并且还可以链接排除和过滤器。这不会增加数据库活动; queryset过滤器等仅在评估queryset本身时执行。请参阅The Django Docs on making queries

修改 事实证明这比我原先想象的要复杂一点,但我相信我已经解决了这个问题(在导入模型声明并进行shell会话之后!)

rooms = Room.objects.filter(DATE FILTERING HERE).annotate(num_persons=Count('hospitalization__room__id')).filter(num_persons__lt=F('max_persons')).count()

将为您提供num_persons(我们的注释变量)小于max_persons的房间数,并预先过滤日期过滤。

请记住包含所需的导入: from django.db.models import Count from django.db.models import F