如何计算Django的当前条纹?

时间:2014-04-24 17:02:15

标签: python django postgresql

对于简单的期刊应用,我有以下模型:

class Journal(models.Model):    
    title = models.CharField(max_length=50)
    created_by = models.ForeignKey(User)

class Entry(models.Model):
    journal = models.ForeignKey(Journal)
    note = models.TextField()
    date = models.DateField()    

我想计算当前条纹:从今天开始,用户提交条目的连续天数。

我有以下函数(非常低效)来计算当前条纹:

def current_streak(journal):
    count = 0
    today = datetime.date.today()
    date = today-datetime.timedelta(days=count) 
    while Entry.objects.filter(journal=journal, date=date).exists():
        count += 1
        date = today-datetime.timedelta(days=count) 
    return count

使用较少的数据库查询计算此值的更好方法是什么?

1 个答案:

答案 0 :(得分:2)

执行此类操作的最佳方法是在一个SQL查询中获取所有日期(并确保Django ORM实际上通过一个SQL查询提取数据),然后处理该信息服务器端:

(请注意,此示例假定日期==今天的单项日记将是1的条纹。)

def current_streak(journal):
    total_streak = 0
    current_streak = 0
    today = datetime.date.today()
    compareDate = today + datetime.timedelta(1) # Tomorrow

    # Using list() here pulls all the entries from the DB at once
    # Gets all entry dates for this journal and whose dates are <= today
    entry_dates = list(Entry.objects.values("date").filter(journal=journal, date__lte = today).order_by("-date"))

    for date in entry_dates:
        # Get the difference btw the dates
        delta = compareDate - date

        if delta.days == 1: # Keep the streak going!
            current_streak += 1
        elsif delta.days == 0: # Don't bother increasing the day if there's multiple ones on the same day
            pass
        else: # Awwww...
            break # The current streak is done, exit the loop

        compareDate = date

    if current_streak > total_streak:
        total_streak = current_streak

    return total_streak

这里有关于Django ORM的一些信息,以及它何时实际从数据库中提取数据:https://docs.djangoproject.com/en/dev/topics/db/queries/#caching-and-querysets