<p>我的解决方案是检查<code>date_from</code>或{<cd2>}字段是否包含在我们感兴趣的时段中。我使用<a href="https://docs.djangoproject.com/en/1.11/topics/db/queries/#complex-lookups-with-q" rel="nofollow noreferrer">^{<cd4>}</a>对象来执行此操作。正如上面的注释中所提到的,我们还需要包括包含我们感兴趣的整个时期的<code>PropertyAvailability</code>对象。如果发现多个实例,则必须检查可用性对象是否连续。在</p>
<pre><code>from datetime import timedelta
from django.db.models import Q
class Property(models.Model):
name = models.CharField(max_length=100)
def is_available(self, avail_date_from, avail_date_to):
date_range = (avail_date_from, avail_date_to)
# Check against the owner's specified availability
query_filter = (
# One of the records' date fields falls within date_range
Q(date_from__range=date_range) |
Q(date_to__range=date_range) |
# OR date_range falls between one record's date_from and date_to
Q(date_from__lte=avail_date_from, date_to__gte=avail_date_to)
)
available_periods = self.propertyavailability_set \
.filter(query_filter) \
.order_by('date_from')
# BEWARE! This might suck up a lot of memory if the number of returned rows is large!
# I do this because negative indexing of a `QuerySet` is not supported.
available_periods = list(available_periods)
if len(available_periods) == 1:
# must check if availability matches the range
return (
available_periods[0].date_from <= avail_date_from and
available_periods[0].date_to >= avail_date_to
)
elif len(available_periods) > 1:
# must check if the periods are continuous and match the range
if (
available_periods[0].date_from > avail_date_from or
available_periods[-1].date_to < avail_date_to
):
return False
period_end = available_periods[0].date_to
for available_period in available_periods[1:]:
if available_period.date_from - period_end > timedelta(days=1):
return False
else:
period_end = available_period.date_to
return True
else:
return False
</code></pre>
<p>不过,我觉得需要指出的是,数据库模型不能保证数据库中没有重叠的<code>PropertyAvailability</code>对象。此外,unique约束很可能包含<code>de_property</code>字段。在</p>