在下面的代码中,我可以看到2个区别问题:
这不是DRY,因为date__range
中的整个逻辑对于两个列表(A和B)都是相同的。你怎么解决这个问题?我尝试使用方法作为参数但没有成功,不确定如何实现它。
在每个循环中调用get_x_events(),我想这样效率不高..
class Event(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)
我的模型以这种方式组织:
感谢。
答案 0 :(得分:1)
这将是一个良好的开端。
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
方法?
答案 1 :(得分:1)
您的查询当然可以进行优化。现在,您为列表推导中的每个迭代执行一个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原则的范围主要取决于模型的逻辑结构,主要是它们的继承链。如果您可以发布模型,我可以帮助您。
答案 2 :(得分:1)
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)