gpt4 book ai didi

python - 在 QuerySet 中合并结果

转载 作者:行者123 更新时间:2023-11-29 12:09:39 25 4
gpt4 key购买 nike

我有以下模型:

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()方法检查是否 Property在给定时间段内通过查询 PropertyAvailability 可用.

除以下情况外,这段代码工作正常:

示例数据

enter image description here

使用当前 Property.is_available()方法,如果我要搜索 2017 年 1 月 2 日2017 年 1 月 5 日 之间的可用性,它会起作用,因为它匹配 #1.

但如果我在 2017 年 1 月 4 日2017 年 1 月 8 日 之间进行搜索,它不会返回任何内容,因为日期范围重叠在多个结果之间 - 它既不匹配 #1 也不匹配 #2

I read this earlier (它通过合并结果引入了类似的问题和解决方案)但是在使用 Django 的 ORM 编写它或让它与原始 SQL 一起工作时遇到了麻烦。

那么,我如何编写一个查询(最好使用 ORM)来执行此操作?或者可能有我不知道的更好的解决方案?

其他说明

两者都是 avail_date_fromavail_date_to必须与 PropertyAvailability 匹配的 date_fromdate_to字段:

  • avail_date_from必须 >= PropertyAvailability.date_from
  • avail_date_to必须 <= PropertyAvailability.date_to

这是因为我需要查询一个Property 给定时间段内可用。

软件规范

  • Django 1.11
  • PostgreSQL 9.3.16

最佳答案

我的解决方案是检查 PropertyAvailabilitydate_fromdate_to 字段是否包含在我们感兴趣的时间段内。我使用 Q 执行此操作对象。正如上面评论中提到的,我们还需要包含包含我们感兴趣的整个时期的 PropertyAvailability 对象。如果我们找到多个实例,我们必须检查可用性对象是否连续.

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

不过我觉得有必要提一下,数据库模型并不能保证您的数据库中没有重叠的 PropertyAvailability 对象。此外,唯一约束最有可能包含 de_property 字段。

关于python - 在 QuerySet 中合并结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43467833/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com