我的方法有以下模型:
class TrendingTopic(models.Model):
categories = models.ManyToManyField('Category', through='TTCategory', blank=True, null=True)
location = models.ForeignKey(Location)
def get_rank(self, t_date=None):
if t_date:
ttcs = self.trendingtopiccycle_set.filter(cycle_time__gt=t_date)
else:
ttcs = self.trendingtopiccycle_set.all()
if ttcs:
return sum([ttc.rank for ttc in ttcs])/len(ttcs)
return 0
def get_day_rank(self,t_date):
ttcs = self.trendingtopiccycle_set.filter(cycle_time__year=t_date.year,
cycle_time__month=t_date.month,
cycle_time__day=t_date.day)
sum_rank = sum([ttc.day_rank for ttc in ttcs if ttc.day_rank])
if sum_rank:
return sum_rank/len(ttcs)
return 0
class TrendingTopicCycle(models.Model):
tt = models.ForeignKey(TrendingTopic)
cycle_time = models.DateTimeField(default=datetime.now)
from_tt_before = models.BooleanField(default=False)
rank = models.FloatField(default=0.0)
day_rank = models.FloatField(default=0.0)
然后我在视图中使用了一些函数来检索所需的信息:
显示当天最热门的热门话题:
def day_topics(tt_date, limit=10):
tts = [(ttc.tt, ttc.tt.get_day_rank(tt_date)) for ttc in \
TrendingTopicCycle.objects.distinct('tt__name') \
.filter(cycle_time__year=tt_date.year,
cycle_time__month=tt_date.month,
cycle_time__day=tt_date.day)]
sorted_tts = sorted(tts, key=itemgetter(1),
reverse=True)[:limit]
return sorted_tts
在确定的时间内显示给定位置(woeid)的最佳热门主题:
def hot_topics(woeid=None, limit=10):
CYCLE_LIMIT = datetime.now() + relativedelta(hours=-5)
TT_CYCLES_LIMIT = datetime.now() + relativedelta(days=-2)
if woeid:
tts = [ttc.tt for ttc in \
TrendingTopicCycle.objects.filter(tt__location__woeid=woeid) \
.distinct('tt__name') \
.exclude(cycle_time__lt=CYCLE_LIMIT)]
else:
tts = [ttc.tt for ttc in \
TrendingTopicCycle.objects.distinct('tt__name') \
.exclude(cycle_time__lt=CYCLE_LIMIT)]
sorted_tts = sorted(tts, key=lambda tt: tt.get_rank(TT_CYCLES_LIMIT),
reverse=True)[:limit]
return sorted_tts
当前解决方案的问题在于它运行速度非常慢,因为它执行了大量查询(100次)来检索数据。我正在使用django调试工具栏来帮助我测量性能。
显然,我正在做一些非常错误的事情,我正在寻找解决方案,我们将非常感谢任何帮助。
编辑:
每个趋势主题都有一组趋势主题周期(ttc)。每个ttc有两个等级:一般(等级)和day_rank。趋势主题等级是通过每个ttc循环计算的。
答案 0 :(得分:1)
首先,请注意django-debug-toolbar虽然很棒,但本身非常慢。如果您注释掉其中间件,则响应时间会显着提高 。这是一个非常有用的工具,不要误会我的意思。我虔诚地使用它,但重点是你不能在你的网站上以“慢速”这样的主观内容为基础进行基准测试。
其次,您的代码有点混乱,因此很难确切地说出您应该做什么。例如,TrendingTopicCycle
有rank
和day_rank
字段,但您从不在发布的代码中使用它们。每次调用get_day_rank
都会发出一个查询,所以如果你只能过滤day_rank
字段本身(不需要那个查询)显然会更有效率,但我无法从代码中看出你如果或当这些字段实际设置时,请在此处。
您可以对代码进行一些小改进,明智地使用select_related
。例如,每次在列表推导中运行ttc.tt.get_day_rank(tt_date))
时,都会发出一个查询以获取tt
,然后在get_day_rank
中发出另一个查询。只需将.select_related('tt')
添加到您的查询集即可至少消除tt
的查询。
另外,我不确定它是否真的导致Django发出不同的查询(也许是一个效率更低的查询),但无论如何,单独过滤year
,{{1 }},和 month
,只过滤完整日期,即:
day
答案 1 :(得分:1)
if ttcs:
return sum([ttc.rank for ttc in ttcs])/len(ttcs)
return 0
这可以由db查询替换。 https://docs.djangoproject.com/en/dev/topics/db/aggregation/
类似的东西:
ttcs.Aggregate(Sum('rank'))["sum__rank"]