python - Django 存储实际可用性并查询新预订的可用时间表
问题描述
在应用程序中,有两种类型的用户:
Student
和Mentor
- 作为
mentor
用户类型,我可以设置基于每周的可用性 - 作为
student
用户类型,我可以看到mentor
可用性。
===============================
所以我根据工作日WeekDay
和AvailableHour
模型存储用户可用性
DAYS_OF_WEEK = (
(0, 'Monday'),
(1, 'Tuesday'),
(2, 'Wednesday'),
(3, 'Thursday'),
(4, 'Friday'),
(5, 'Saturday'),
(6, 'Sunday'),
)
class WeekDay(models.Model):
mentor = models.ForeignKey(
User,
on_delete=models.CASCADE,
related_name="weekday"
)
weekday = models.IntegerField(choices=DAYS_OF_WEEK)
class AvailableHour(models.Model): #Based on weekday
weekday = models.ForeignKey(
WeekDay,
on_delete=models.CASCADE,
related_name="available_hour"
)
from_hour = models.TimeField()
to_hour = models.TimeField()
- 作为用户类型
student
,我只能在mentor
可用时间预订会话。
因此,当学生预订课程时,我们会将信息存储在模型下方。
class BookingSession(models.Model):
student = models.ForeignKey(
User,
on_delete=models.CASCADE,
related_name="student_booking"
)
mentor = models.ForeignKey(
User,
on_delete=models.CASCADE,
related_name="mentor_booking"
)
date = models.DateField()
from_hour = models.TimeField()
to_hour = models.TimeField()
那么现在有什么问题呢?
由于我们有用户AvailableHour
,所以一旦学生预订了导师课程,那么指定的时间范围是无法获得导师资料的,对吧?以便其他学生可以看到导师的实际可用性。
所以你知道,如果我们从中获取查询集AvailableHour
,并不意味着如果任何指定的时间范围已经预订并且预订的时间已经存储在BookingSession
模型中,那么导师在那个时间可用
如果指定工作日AvailableHour
中存在开始和结束时间,我想排除的记录BookingSession
我想向学生展示,导师的实际可用性是什么。
如果您知道它已经有预订,就像AvailableHour
无法存储实际可用的一样!BookingSession
假设我在BookingSession
表中有数据
booked_sesson = [
{'date': '2021-08-02','from_hour': '12:30', 'to_hour': '12:15' }, # monday
{'date': '2021-08-04','from_hour': '02:30', 'to_hour': '03:15' }, # Wednesday
]
和下面的WeekDay
可用性AvailableHour
表数据
available_based_on_weekday = [
{
"weekday": 1, 'opening_hour_time': [ # monday
{'from_hour': '12:30', 'to_hour': '12:15'},
{'from_hour': '12:30', 'to_hour': '12:15'},
{'from_hour': '12:30', 'to_hour': '12:15'}
]
},
{
"weekday": 7, 'opening_hour_time': [ # Saturday
{'from_hour': '13:30', 'to_hour': '15:15'},
{'from_hour': '15:30', 'to_hour': '16:15'},
{'from_hour': '19:30', 'to_hour': '20:15'},
{'from_hour': '23:30', 'to_hour': '23:45'}
]
},
{
"weekday": 3, 'opening_hour_time': [ # Wednesday
{'from_hour': '02:30', 'to_hour': '03:30'},
{'from_hour': '17:30', 'to_hour': '18:15'},
{'from_hour': '19:30', 'to_hour': '20:15'},
{'from_hour': '21:30', 'to_hour': '22:30'}
]
}
]
我期待什么输出结果? 查询后,我期待这些输出,并且应该逐月查询:
actual_availability = [
{
'date': '2021-08-01',
'available': []
},
{
'date': '2021-08-02',
'available': [
{'from_hour': '12:30', 'to_hour': '12:15'},
{'from_hour': '12:30', 'to_hour': '12:15'}
]
},
{
'date': '2021-08-03',
'available': []
},
{
'date': '2021-08-04',
'available': [
{'from_hour': '03:15', 'to_hour': '03:30'},
{'from_hour': '17:30', 'to_hour': '18:15'},
{'from_hour': '19:30', 'to_hour': '20:15'},
{'from_hour': '21:30', 'to_hour': '22:30'}
]
},
{
'date': '2021-08-05',
'available': []
},
{
'date': '2021-08-06',
'available': []
},
{
'date': '2021-08-07',
'available': []
},
{
'date': '2021-08-08',
'available': []
},
{
'date': '2021-08-09',
'available': [
{'from_hour': '12:30', 'to_hour': '12:15'},
{'from_hour': '12:30', 'to_hour': '12:15'},
{'from_hour': '12:30', 'to_hour': '12:15'}
]
},
# to be continued for a month by month
]
如果您有任何替代方法,我会欢迎,请在这里分享您的观点。
给你我试过的东西,它真的很愚蠢,不起作用。
real_available_date_slot = []
for obj in BookingSession.objects.filter(mentor_id='A mentor ID'):
weekday = obj.date.isoweekday()
real_available = []
available_hour = AvailableHour.objects.filter(weekday__weekday=weekday, weekday__mentor=obj.mentor)
availables = available_hour.exclude(
from_hour__gt=obj.to_hour
).exclude(
to_hour__lt=obj.to_hour
)
for available in availables:
real_available.append(
{'from_hour': available.from_hour, 'to_hour': available.to_hour}
)
real_available_date_slot.append({
obj.date: real_available
})
我也尝试过不同的其他方式,但我无法提供任何解决方案
谁能分享您的想法,我们如何解决我的availability
问题?您查询此类事情的方法是什么?或者我为这种情况做了不正确的数据库设计?
解决方案
另一种方法,并以@Jimmar 的答案为基础,有一些变化:
Availability
可以保存导师信息和导师的可用时间表。因此,导师可以有许多关于其可用性关系的项目,其中包括工作日信息以及时间段。
class Availability(models.Model):
mentor = models.ForeignKey(
User,
on_delete=models.CASCADE,
related_name="availability"
)
weekday = models.IntegerField(choices=DAYS_OF_WEEK)
from_hour = models.TimeField()
to_hour = models.TimeField()
例如,导师可以有这种可用性:
{'id': 1, 'mentor': 1, 'weekday': 1, 'from_hour': '12:15', 'to_hour': '12:45'}
{'id': 2, 'mentor': 1, 'weekday': 1, 'from_hour': '12:45', 'to_hour': '13:15'}
{'id': 3, 'mentor': 1, 'weekday': 1, 'from_hour': '13:15', 'to_hour': '14:45'}
反过来,Bookings
现在可以保持student
and mentor_session
( Availability
) 关系,但与预定日期。这将支持获取Availability
项目并按预订日期排除。
class BookingSession(models.Model):
student = models.ForeignKey(
User,
on_delete=models.CASCADE,
related_name="bookings"
)
mentor_session = models.ForeignKey(
Availability,
on_delete=models.CASCADE,
related_name="bookings"
)
date = models.DateField()
例如,如果我们有以下预订:
{'id': 1, 'student': 1, 'mentor_session': 1, 'date': '2021-01-01'}
{'id': 2, 'student': 1, 'mentor_session': 1, 'date': '2021-01-02'}
{'id': 3, 'student': 1, 'mentor_session': 1, 'date': '2021-01-03'}
这意味着导师的可用性 id 1 由 id 1 的学生在上述日期预订。所以现在要根据日期获取导师的可用时间:
date = datetime.date(2021, 01, 01)
weekday = date.isoweekday()
Availability.objects.filter(mentor=mentor, weekday=weekday).annotate(
is_booked_on_date=Exists(
BookingSession.objects.filter(mentor_session=OuterRef('pk'), date=date)
)
).filter(is_booked_on_date=False)
由于 ID 为 1 的可用性已在指定日期预订(它有一个预订会话),这应该只返回 date 的可用性 ID 2 和 3 2021-01-01
。
为了支持您想要的预期输出,您可以在特定日期范围内迭代每一天并使用上述查询的结果。
推荐阅读
- jquery - 将 div 内部的滚动匹配到另一个外部 div
- java - 重用 bean 的 XML 片段
- c# - 将可执行文件包含到 UWP 最终包中
- c# - 在 GetLogger 上调用特定记录器的自定义 PatternLayout
(); - r - 在安装另一个导入它的包时,为 plotly 包设置绝对包路径
- text - 尽管设置了新的 ttf 文件,Godot 脚本编辑器字体不会改变
- java - 不允许向该商家付款(客户 ID 无效)
- python - 将 pandas DataFrame 转换为 dict 并保留重复索引
- python - How to use the lxml to scrape a table and grab the href links?
- python - 从 tkinter 列表框中永久添加/删除项目