我有以下型号:
class Property(models.Model):
name = models.CharField(max_length=100)
def is_available(self, avail_date_from, avail_date_to):
# Check against the owner's specified availability
available_periods = self.propertyavailability_set \
.filter(date_from__lte=avail_date_from, \
date_to__gte=avail_date_to) \
.count()
if available_periods == 0:
return False
return True
class PropertyAvailability(models.Model):
de_property = models.ForeignKey(Property, verbose_name='Property')
date_from = models.DateField(verbose_name='From')
date_to = models.DateField(verbose_name='To')
rate_sun_to_thurs = models.IntegerField(verbose_name='Nightly rate: Sun to Thurs')
rate_fri_to_sat = models.IntegerField(verbose_name='Nightly rate: Fri to Sat')
rate_7_night_stay = models.IntegerField(blank=True, null=True, verbose_name='Weekly rate')
minimum_stay_length = models.IntegerField(default=1, verbose_name='Min. length of stay')
class Meta:
unique_together = ('date_from', 'date_to')
从本质上讲,每个Property
的可用性都是用PropertyAvailability
的实例指定的。由此,Property.is_available()
方法通过查询PropertyAvailability
来检查{
示例数据
使用当前的Property.is_available()
方法,如果我要搜索2017年1月2日2日和2017年1月5日eem>之间的可用性,因为它匹配1。在
但如果我在2017年1月4日和2017年1月8日之间进行搜索,它不会返回任何内容,因为日期范围在多个结果之间重叠-它既不匹配\1或\2。在
I read this earlier(它通过合并结果引入了一个类似的问题和解决方案),但是在编写使用Django的ORM或使其与原始SQL一起工作时遇到了困难。在
那么,我如何编写一个查询(最好使用ORM)来实现这一点呢?或者也许有更好的解决方案我不知道?在
avail_date_from
和avail_date_to
必须与PropertyAvailability
的date_from
和{
avail_date_from
必须是>;=PropertyAvailability.date_from
avail_date_to
必须是<;=PropertyAvailability.date_to
这是因为我需要查询在给定的时间段内Property
是否可用。在
我的解决方案是检查}字段是否包含在我们感兴趣的时段中。我使用^{} 对象来执行此操作。正如上面的注释中所提到的,我们还需要包括包含我们感兴趣的整个时期的
date_from
或{PropertyAvailability
对象。如果发现多个实例,则必须检查可用性对象是否连续。在不过,我觉得需要指出的是,数据库模型不能保证数据库中没有重叠的
PropertyAvailability
对象。此外,unique约束很可能包含de_property
字段。在应该能够做的是聚合要查询的数据,并合并任何重叠(或相邻)范围。在
Postgres没有任何方法做到这一点:它有用于并集和合并相邻范围的运算符,但没有任何运算符可以聚合重叠/相邻范围的集合。在
但是,您可以编写一个查询来组合它们,尽管如何使用ORM来实现这一点还不明显。在
这里有一个解决方案(作为http://schinckel.net/2014/11/18/aggregating-ranges-in-postgres/#comment-2834554302上的注释留下,并进行了调整以组合相邻的范围,这似乎是您想要的):
在ORM中可以查询的一种方法是将它放在Postgres视图中,并有一个引用它的模型。在
但是,值得注意的是,它查询整个源表,因此您可能希望应用筛选;可能是通过
de_property
。在比如:
^{pr2}$另外,您可能需要考虑使用Postgres的date range对象,因为这样可以防止
start > finish
(自动),也可以使用排除约束来防止给定属性的句点重叠。在最后,另一种解决方案可能是生成一个派生表,该表存储un的可用性,基于获取可用周期并反转它们。这使得编写查询更简单,因为您可以编写直接重叠,但求反(也就是说,如果没有重叠的不可用时段,属性对于给定的时段是可用的)。我在一个生产系统中对员工的可用性/不可用性进行检查,在这个系统中需要进行许多检查。请注意,这是一个非规范化的解决方案,它依赖于触发器函数(或其他更新)来确保它保持同步。在
相关问题 更多 >
编程相关推荐