2014-10-08 36 views
1

我有一個模型方法,可以在我的模型中使用HN排名算法來計算投票的得分,該算法還可以緩存每個得分。 calculate_score()是這裏關注的主要內容。Django:order_by API json值或緩存對象

class Submission(models.Model): 
    submission_type = models.CharField(_('Submission Type'), 
             max_length=255, 
             choices=tuple([(media.name.lower(), media.value) for media in MediaTypes]), 
             blank=False) 
    title = models.CharField(_('Title'), max_length=100, blank=False) 
    url = models.URLField(_('Link'), blank=False) 
    description = models.TextField(_('Description')) 
    flagged = models.BooleanField(_('Is Flagged for Review'), default=False) 
    user = models.ForeignKey(User, related_name='user_submissions') 
    thumbnail = models.ImageField() 
    date_submitted = models.DateTimeField(default=timezone.now) 

    by_votes = VoteCountManager() 
    objects = models.Manager() 

    def __str__(self): 
     return self.submission_type + ': ' + self.title 

    def get_absolute_url(self): 
     return reverse('submit_detail', args=[ 
      str(self.submission_type), 
      str(self.id), 
     ]) 

    def get_vote(self): 
     """ 
     Returns the number of votes associated with a particular submission 
     :return: int 
     """ 
     return self.submission_votes.count() 

    def calculate_score(self): 
     """ 
     This is a variation of the HN ranking algorithm 
     :return: score 
     """ 
     secs_in_hour = float(60 * 60) 
     g = 1.2 

     delta = timezone.now() - self.date_submitted 
     item_hour_age = delta.total_seconds()/secs_in_hour 
     votes = self.submission_votes.count() - 1 
     score = votes/pow((item_hour_age + 2), g) 
     cached = cache.get('s{0}'.format(self.pk)) 
     if not cached: 
      cache.set('s{0}'.format(self.pk), score, 30) 
     return score 

我使用我的序列化模型djangorestframework

class SubmissionSerializer(serializers.HyperlinkedModelSerializer): 
    score = serializers.SerializerMethodField('rank') 

    class Meta: 
     model = Submission 

    def rank(self, obj): 
     return obj.calculate_score() 

我有兩種方法,我想我能解決我的問題,但我不知道該怎麼辦它們中的,我不確定哪一個是最好的。因爲我爲每個提交的文件緩存了score。我試圖責令提交在ListView像這樣從緩存中拉:

class SubmissionList(ListView): 
    model = Submission 
    def get_queryset(self): 
     return super(SubmissionHotList, self).get_queryset().annotate(
      score=cache.get('s{0}'.format(x) for x in Submission.pk) 
      votes=models.Count('submission_votes'), 
     ).order_by(
      '-score', '-votes', 
     ) 

但是我發現order_by僅適用於數據庫級,我不得不創建一個數據庫字段所計算的得分,如果可能,我希望避免這種情況。我的其他可能性是在我的API中使用Submission這個ListView中的序列化數據,但是我不確定API是否僅適用於外部應用程序,或者我是否可以在生成API的相同應用程序中使用它們。

我想我的問題是。讓緩存對象按特定順序列出每個提交,還是使用API​​來完成此操作會更好?如果我使用API​​,我怎麼能解析和訂購ListView中的JSON數據,同時保持votes作爲輔助訂購機制?

回答

0

,如果你想顯示無分頁的所有項目,你會不會,如果你這樣做

import operator 

class SubmissionList(TemplateView): 

    template_name = "submissions.html" 

    def get_context_data(self, **kwargs): 
     context = super(SubmissionList, self).get_context_data(**kwargs) 
     submissions = Submission.objects.all().annotate(
      votes=models.Count('submission_votes') 
     ) 
     sorted_submissions = sorted(submissions, key=lambda x:(cache.get('s{0}'.format(x.pk)), x.votes), reverse=True) 
     context['submissions'] = sorted_submissions 

     return context 
+0

損失任何性能這是完美的!非常感謝。 – joshchandler 2014-10-08 15:36:07