Django通过预订日期过滤外键

时间:2013-07-23 09:50:40

标签: python django date

我有以下型号:

class House(models.Model): 
   Name = models.CharField(max_length=200, unique=True) 
   Reference = models.CharField(max_length=50, unique=True)

class Booking(models.Model): 
   House = models.ForeignKey(House, related_name='booking')
   InitialDate = models.DateField()
   FinalDate= models.DateField()

现在,我想执行查询以过滤范围日期的所有可用房屋(例如:2013-07-21至2013-07-30),因此它应排除所有预订开始和结束的房屋在这两个日期之间。 我可以使用原始SQL执行此查询,但不能使用django语法执行此查询。

有人可以帮忙吗?

非常感谢!

4 个答案:

答案 0 :(得分:4)

当使用Django ORM时,使用的一种做法是,你应该始终以你想要结束的关系开始,在你的情况下House

我认为这将是你实现目标的方式:

unbooked_houses = House.objects.exclude(
    booking__InitialDate__gte=start_date, booking_FinalDate__lte=end_date)

通过这种方式,您最终会得到QuerySet,无需担心列表推导等等。

此外,Python PEP-8文档规定您应遵循以下变量和属性的命名约定:

而不是InitialDate,最好是initial_date

答案 1 :(得分:3)

我采取了更自由的案例。

class House(models.Model): 
    name = models.CharField(max_length=200, unique=True) 
    reference = models.CharField(max_length=50, unique=True)

class Booking(models.Model): 
    house = models.ForeignKey(House, related_name='booking')
    initial_date = models.DateField()
    final_date= models.DateField()

import datetime
start_date = datetime.datetime(2013, 07, 21)
end_date = datetime.datetime(2013, 07, 30)

# so simply intersect
booked = set(values['house_id'] for values in Booking.objects.objects.filter(
    initial_date__lte=end_date, final_date__gte=start_date).values('house_id'))

House.objects.exclude(id__in=booked)

thanx to richsilv的设定理念,合乎逻辑,但我通过阅读他的答案来了解它。它只是通过使用不同的房屋来简化sql语句。

答案 2 :(得分:0)

假设您所谈论的时间段介于startdateenddate之间,那么这会有效吗?

booked = set([x.House.Reference for x in \
   Booking.objects.filter(InitialDate__lte=enddate).filter(FinalDate__gte=startdate)])
available = House.objects.exclude(Reference__in=booked)

答案 3 :(得分:0)

由于Django创建的反向关系,可以直接过滤:

bookedHouses = House.objects.filter(booking__InitialDate__lte=enddate)\ .filter(booking__FinalDate__gte=startdate)