评估查找已知对象
问题描述:
我沿着这些线路滤波器:评估查找已知对象
class EventManager(models.Manager):
def joinable(self, current_time):
query = Q(join_time__lte=current_time) & Q(end_time__gte=current_time)
return self.filter(query)
所以,对于一个时间,返回,你可以参加活动。我也想一个can_join
方法添加到事件:
class Event(models.Model):
def is_joinable(self, current_time):
return self.join_time <= current_time & self.end_time >= current_time
但我想,以避免重复在此逻辑(实际逻辑是一个有点复杂,它可能会发生变化)。 is_joinable
有没有方法来评估查询并确定self
是否会通过它?或者我可以在其他方法上写两种方法吗?很显然,我可以做类似
query = Q(id=self.id) & joinable_query
return Event.objects.filter(query).exists()
但似乎对我已经在我的指尖记录无谓的额外的数据库查询。
答
您可以使用query expression在数据库上执行该计算,并将结果注释为布尔型字段,然后过滤该字段。
喜欢的东西:
class EventManager(models.Manager):
def get_queryset(self):
return self.annotate(
joinable=Case(
When(start_date__lte=now, end_date__gte=now, then=Value(True)),
default=Value(False),
output_field=models.BooleanField()
))
现在你可以在Event.objects.filter(joinable=True)
过滤,每个事件对象将永远有一个joinable
场与TRUE或FALSE值。 (注意,由于该字段是由数据库计算出来的,如果一个事件在内存中改变了它的可连接状态 - 或者是因为你明确地改变了日期,或者是因为日期到期了 - 可连接的字段不会是在实践中这应该不是什么大问题。)
这是非常有趣的,但是与“现在”紧紧相连。因此,如果在对象的生命期间它改变状态(因为时间流逝,而这些对象被长期存在的芹菜任务使用),它不会更新。我一直在避免让模型自己单独看“现在”,因为它让单元测试变得如此脆弱;这就是为什么我将current_time传递给is_joinable函数的原因。尽管如此,仍然非常有趣。 (无论如何,长寿命的模型对象都是一个问题,因为它们可能会以其他方式在我背后改变。) –
是的,我在我的答案中注意到了这一点。我没有看到有什么替代方法:要么将数据库中的值作为查询的一部分进行计算,要么将其作为Python方法进行计算,或者重复逻辑。 –