如何让我的Django代码DRY和高效使用全面的列表



在下面的代码中,我可以看到两个不同的问题:

  1. 这不是DRY,因为date__range中的整个逻辑对于两个列表(A和B)都是相同的。您将如何解决这个问题?我尝试用方法作为参数没有成功,不确定理解如何实现这一点。

  2. 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)
]

除此之外,你可能应该重构你的模型。拥有EventAEventB而不是单个Event模型表明您进一步违反了DRY原则。同样适用于get_A_eventsget_B_events方法,为什么不单独的get_events方法?

最新更新