如何在Django中计算当前连续记录?
我有一个简单的日记应用,里面有以下这些模型:
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 个回答
4
做这种事情最好的方法是一次性通过一个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