我对 Django 比较陌生,这是我在论坛上的第一篇文章。
以下是应用程序中使用的模型(简化)。 该应用程序是关于在给定时间段内保留一组资源。
from django.db import models
class Resource(models.Model):
id = models.AutoField(primary_key=True)
serialno = models.CharField(max_length=30, null=False, unique=True)
name = models.CharField(max_length=40, null=False)
def __str__(self):
return f"{self.name}/{self.serialno}"
class Reservations(models.Model):
id = models.AutoField(primary_key=True)
active = models.BooleanField(default=True)
name = models.CharField(max_length=30, null=False)
startdate = models.DateField(null=False)
enddate = models.DateField(null=False)
resource = models.ManyToManyField("myapp.Resource", db_table="myapp_resource_reservations", related_name="reservations")
def __str__(self):
return f"{self.name}/{self.startdate}/{self.enddate}"
例如,以下是模型中存在的数据
资源(格式:名称/序列号)
>>> Resource.objects.all()
<QuerySet [<Resource: Resource1/RES1>, <Resource: Resource2/RES2>, <Resource: Resource3/RES3>, <Resource: Resource4/RES4>]>
>>>
预订(格式:姓名/开始日期/结束日期/活动) Resource1
的所有预订>>> Reservations.objects.all()
<QuerySet [<Reservations: Booking1/2023-03-01/2023-03-07/True>, <Reservations: Booking2/2023-03-15/2023-03-22/True>, <Reservations: BookingX/2023-03-08/2023-03-14/False>]>
>>>
我正在尝试使用以下查询检索在给定日期期间没有“活动”预订的所有资源。
>>> Resource.objects.exclude((Q(reservations__startdate__range=('2023-03-08','2023-03-14')) | Q(reservations__enddate__range=('2023-03-08','2023-03-14'))) & Q(reservations__active=True))
<QuerySet [<Resource: Resource2/RES2>, <Resource: Resource3/RES3>, <Resource: Resource4/RES4>]>
>>>
Resource1 确实有预订:2023-03-08 到 14 期间的 BookingX,但它是 active=False。我希望“Resource1”出现在上面的排除查询中,但它没有出现(预期逻辑:“排除日期范围内具有 active=True 保留的所有资源”)。
有人可以帮助理解为什么结果不如预期吗?我做错了什么?
尝试使用“过滤器”而不是“排除”,它的行为符合预期。
>>> Resource.objects.filter((Q(reservations__startdate__range=('2023-03-08','2023-03-14')) | Q(reservations__enddate__range=('2023-03-08','2023-03-14'))) & Q(reservations__active=True))
<QuerySet []>
>>>
>>> Resource.objects.filter((Q(reservations__startdate__range=('2023-03-08','2023-03-14')) | Q(reservations__enddate__range=('2023-03-08','2023-03-14'))) & Q(reservations__active=False))
<QuerySet [<Resource: Resource1/RES1>]>
>>>
您基本上是在告诉 ORM 排除所有具有任何活动保留的资源。因为
&
首先被评估(在 |
之前)所以范围内的内容并不重要,因为它已经排除了 Resource 1 在这一点上。