在下面的代码中,我可以看到两个不同的问题:
-
这不是DRY,因为
date__range
中的整个逻辑对于两个列表(A和B)都是相同的。您将如何解决这个问题?我尝试用方法作为参数没有成功,不确定理解如何实现这一点。 -
get_x_events()在每个循环中被调用,我猜这是不高效的。
类事件(models.Model):
@classmethod
def get_stats(cls, owner, nb_days, offset):
# Building a list with comprehensive list calling the get_A_events() classmethod of the EventA class
list_A = [EventA.get_A_events(owner).filter(
date__range=(
now_day - timedelta(days=offset) - timedelta(days=d),
now_day - timedelta(days=offset) - timedelta(days=d-1))).count()
for d in range(nb_days)]
# Doing the same with another method of another class
# The logic is exactly the same thought...
list_B = [EventB.get_B_events(owner).filter(
date__range=(
now_day - timedelta(days=offset) - timedelta(days=d),
now_day - timedelta(days=offset) - timedelta(days=d-1))).count()
for d in range(nb_days)]
return zip(list_A, list_B)
我的模型是这样组织的:
- 类事件(models.Model)
- 类EventA(事件)
- 类EventB(事件)
谢谢。
def get_events_list(event_object_with_owner, offset, nb_days):
event_list = [
event_object_with_owner.filter(
date__range=(
now_day - timedelta(days=offset) - timedelta(days=d),
now_day - timedelta(days=offset) - timedelta(days=d-1))).count()
for d in range(nb_days)
]
return event_list
event_list_A = get_events_list(EventA.get_A_events(owner), offset, nb_days)
event_list_B = get_events_list(EventB.get_B_events(owner), offset, nb_days)
您的查询当然可以优化。现在,对列表推导式中的每个迭代执行一个sql查询。使用注释,您可以将其减少到2个查询:
from django.db.models import Count
list_A = [a['num_days'] for a in EventA.get_A_events(owner).filter(date__range=(
now_day - timedelta(days=offset),
now_day - timedelta(days=offset+nb_days)))
.values('date').annotate(num_days=Count('id'))]
您可以使用**kwargs
作为过滤器调用,正如Matt建议的那样,但是您可以在多大程度上坚持DRY原则主要取决于您的模型的逻辑结构,主要是它们的继承链。如果你能把你的模型贴出来,我也许能进一步帮助你。
这将是一个良好的开端。
kwargs = {
'date__range': (now_day - timedelta(days=offset) - timedelta(days=d),
now_day - timedelta(days=offset) - timedelta(days=d-1)),
}
list_A = [
EventA.get_A_events(owner).filter(**kwargs).count()
for d in range(nb_days)
]
list_B = [
EventB.get_B_events(owner).filter(**kwargs).count()
for d in range(nb_days)
]
除此之外,你可能应该重构你的模型。拥有EventA
和EventB
而不是单个Event
模型表明您进一步违反了DRY原则。同样适用于get_A_events
和get_B_events
方法,为什么不单独的get_events
方法?