1

我正在使用 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比较。

你有什么想法吗?

编辑

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

因此,根据 Karl 在下面的建议,我尝试使用:

  • 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'))
    • 没有任何结果([]),而根据我当前的数据库,我预计至少有三个结果。
    • When removing .exclude(), I still get no results. It looks like the .annotate() I'm using is doing something wrong.
4

1 回答 1

1

I believe that something similar to Room.objects.filter(hospitalization__date_out="2014-04-25", max_persons__lt=x) should do the trick. Remember that you can have multiple declarations in a filter operation, and that you can also chain both exclusions and filters. This doesn't add to database activity; queryset filters and the like are only executed when the queryset itself is evaluated. See The Django Docs on making queries.

EDIT: This actually turned out to be slightly more complicated than I first thought, but I believe I have worked it out (after importing your model declarations and having a shell session!)

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

Will give you the number of rooms in which num_persons (our annotated variable above) is less than max_persons, with the date filtering occurring beforehand.

Remember to include the required imports: from django.db.models import Count from django.db.models import F

于 2014-04-19T15:30:12.033 回答