0

私はdjango-votingを使用してアプリケーションに取り組んでおり、 Eric FlorenzanoのカスタムVoteAwareManagerテクニックを使用してホームページアイテムのソート順を調整しています:

models.py

class VoteAwareManager(models.Manager):
    """ Get top votes. hot = VoteAwareManager() """
    def _get_score_annotation(self):
        model_type = ContentType.objects.get_for_model(self.model)
        table_name = self.model._meta.db_table
        return self.extra(select={
            'score': 'SELECT COALESCE(SUM(vote),0) FROM %s WHERE content_type_id=%d AND object_id=%s.id' %
                (Vote._meta.db_table, int(model_type.id), table_name)
                }
        )

    def most_loved(self,):
        return self._get_score_annotation().order_by('-score')

    def most_hated(self):
        return self._get_score_annotation().order_by('score')

class Post(models.Model):
    """Post model"""
    title = models.CharField(_("title"), max_length=200, blank=False)
    slug = models.SlugField(_("slug"), blank=True)
    author = models.ForeignKey(User, related_name="added_posts")
    kind = models.CharField(max_length=1, choices=KIND, default=1)
    url = models.URLField(blank=True, null=True, help_text="The link URL", default='')
    content_markdown = models.TextField(_("Entry"), blank=True)
    content_html = models.TextField(blank=True, null=True, editable=False)
    status = models.IntegerField(_("status"), choices=STATUS_CHOICES, default=IS_PUBLIC)
    allow_comments = models.BooleanField(_("Allow Comments?"), blank=False, default=1)
    created_at = models.DateTimeField(_("created at"), default=datetime.now)
    updated_at = models.DateTimeField(_("updated at"))

    objects = models.Manager()
    hot = VoteAwareManager()

ビュー.py

def homepage(request): 
"""Show top posts"""   
return object_list(request, 
    queryset=Post.hot.most_loved().filter(status=IS_PUBLIC),
    template_name='homepage.html',
    template_object_name='post',
    extra_context= {'profile': get_profiles}
)

古いアイテムのランクが下がるように、 Hacker New のランキング アルゴリズムを上記のコードと組み合わせたいのですが、問題が発生しています。関連するコードを VoteAwareManager 関数に入れるか、most_loved メソッドに入れるか、またはまったく別の場所に入れるかはわかりません。

以下は私が試したことです:

1. most_loved メソッドでの計算:戻り値TypeError at / unsupported operand type(s) for -: 'QuerySet' and 'int'(結果を取得できるかどうかを確認するためだけにランダムなタイムスタンプを使用する場合、最終的にはオブジェクトのタイムスタンプを取得する方法も理解する必要があります — 私はプログラミング初心者です):

def most_loved(self):
    totalscore = self._get_score_annotation()
    time_stamp = 20120920
    gravity = 1.8
    return (totalscore - 1) / pow((time_stamp+2), gravity)

2. SQL での計算:戻り値TemplateSyntaxError at / Caught DatabaseError while rendering: column "votes.time_stamp" must appear in the GROUP BY clause or be used in an aggregate function LINE 1: ...(SELECT COALESCE(SUM(vote),0 / (EXTRACT(HOUR FROM TIME_STAMP...:

class VoteAwareManager(models.Manager):
""" Get top votes. hot = VoteAwareManager() """
def _get_score_annotation(self):
    model_type = ContentType.objects.get_for_model(self.model)
    table_name = self.model._meta.db_table
    return self.extra(select={
        'score': 'SELECT COALESCE(SUM(vote),0 / (EXTRACT(HOUR FROM TIME_STAMP)+2 * 1.8)) FROM %s WHERE content_type_id=%d AND object_id=%s.id' % 
        (Vote._meta.db_table, int(model_type.id), table_name)
        }
    )

1 つのオプションは、投票システムをdjango-rangevotingを使用するように変更しようとすることですが、可能であればこれを django-voting で動作させたいと考えています。どんな助けでも大歓迎です。

4

1 に答える 1

2

完璧ではありません (ユーザー自身の投票を無効にするために -1 減算を省略しています) が、これは今のところ十分に機能しているようです:

class VoteAwareManager(models.Manager):
""" Get recent top voted items (hacker news ranking algorythm, without the -1 for now since it breaks the calculation as all scores return 0.0)
    (p - 1) / (t + 2)^1.5
    where p = points and t = age in hours
"""
def _get_score_annotation(self):
    model_type = ContentType.objects.get_for_model(self.model)
    table_name = self.model._meta.db_table

    return self.extra(select={

        'score': 'SELECT COALESCE(SUM(vote / ((EXTRACT(EPOCH FROM current_timestamp - created_at)/3600)+2)^1.5),0) FROM %s WHERE content_type_id=%d AND object_id=%s.id' % (Vote._meta.db_table, int(model_type.id), table_name)

        })

def most_loved(self):        
    return self._get_score_annotation().order_by('-score',)
于 2012-10-01T09:51:09.320 に答える