【问题标题】:Sorting by user upvotes and downvotes not working properly按用户赞成和反对票排序无法正常工作
【发布时间】:2021-11-07 04:05:18
【问题描述】:

我目前有这样的模型

class IpAddress(models.Model):
    creado = models.DateTimeField(auto_now_add=True)
    ip_address = models.GenericIPAddressField(unique=True)

class Palabra(models.Model):
    nombre = models.CharField(max_length=250)
    definicion = models.CharField(max_length=1000, unique=True)
    ejemplo = models.CharField(max_length=250)
    creado = models.DateTimeField(auto_now_add=True)
    user = models.ForeignKey(CustomUser, on_delete=models.SET_NULL, null=True, blank=True)
    anonimo = models.BooleanField(default=True)
    aprobada = models.BooleanField(default=False)
    userUpVotes = models.ManyToManyField(IpAddress, blank=True, related_name='threadUpVotes')
    userDownVotes = models.ManyToManyField(IpAddress, blank=True, related_name='threadDownVotes')
    gramatica = models.CharField(max_length=250, null=True, blank=True)
    pais = models.CharField(max_length=250, null=True, blank=True)

而我的排名功能就是这样

        defeniciones = Palabra.objects.prefetch_related(
            'tag_set'
        ).filter(
            nombre__iexact=palabra,
            aprobada=True
        ).annotate(
            total_votes=Count('userUpVotes') / NullIf((Count('userUpVotes') + Count('userDownVotes')), 0)).order_by('-total_votes')

我有一个单词有两个赞成票而没有反对票的情况。但是没有赞成或反对的词排名更高。

由于 postgres,我正在使用 NullIf

一个例子是here,它以 1 个赞成票排名第一,而以 6 个赞成票排名第一。

全景

class PalabraView(View):
    def get(self, request, palabra=None):
        defeniciones = Palabra.objects.prefetch_related(
            'tag_set'
        ).filter(
            nombre__iexact=palabra,
            aprobada=True
        ).annotate(total_upvotes=Count('userUpVotes'),
                   total_votes=Count('userUpVotes') / NullIf((Count('userUpVotes') + Count('userDownVotes')),
                                                             0)).order_by(F('total_votes').desc(nulls_last=True),
                                                                          "-total_upvotes")
        for post in defeniciones:
            post.up_votes = post.userUpVotes.all()
            post.down_votes = post.userDownVotes.all()
            tags = post.tag_set.all()
            post.sins = ', '.join(['<a href="/significado/%s/">%s</a>' % (
                str(item).lower().strip('.'),
                str(item).lower().strip('.'),
            ) for item in tags.filter(tag_type='Sinónimo')])
            post.ants = ', '.join(['<a href="/significado/%s/">%s</a>' % (
                str(item).lower().strip('.'),
                str(item).lower().strip('.'),
            ) for item in tags.filter(tag_type='Antónimo')])

        paginator = Paginator(defeniciones, 20)  # Show 25 contacts per page.
        page_number = request.GET.get('page')
        page_obj = paginator.get_page(page_number)
        add_word = False
        ipaddress = IpAddress.get_my_ip(request)
        if defeniciones.count() == 0:
            add_word = True
        context = {
            'add_word': add_word,
            'palabra': palabra,
            'defeniciones': defeniciones,
            'title': '%s: Significado de %s - DiccionarioEspañol.com' % (palabra.capitalize(), palabra),
            'description': '%s: Significado de %s en DiccionarioEspañol.com' % (palabra.capitalize(), palabra),
            'page_obj': page_obj,
            'ipaddress': ipaddress,
            'countries': COUNTRIES
        }

        return render(request, 'palabra.html', context)

【问题讨论】:

  • 你的问题可能在于你的total_votes计数,我建议你应该让total_votes = userUpVotes - userDownVotes

标签: python python-3.x django


【解决方案1】:

total_votes 表示 0 次赞成和 0 次反对的词等于 NULL。你可以这样检查:

SELECT 0 / NULL;
---
<null>

当您对DESC 进行排序时,NULL 的排名也高于所有内容,例如:

SELECT * FROM (VALUES (NULL), (1), (NULL)) "n" ORDER BY "n" DESC;
---
<null>
<null>
1

所以你只需要添加NULLS LAST 就可以了:

from django.db.models import F  

...

defeniciones = Palabra.objects.prefetch_related(
    'tag_set'
).filter(
    nombre__iexact=palabra,
    aprobada=True
).annotate(
    total_votes=Count('userUpVotes') /
                NullIf((Count('userUpVotes') + Count('userDownVotes')), 0)
).order_by(F('total_votes').desc(nulls_last=True))

【讨论】:

  • 我添加了这个,它仍然将赞成票最少的那张排在赞成票多的那张之上。
  • 我认为您的问题出在“2 / 0”和“0 / 0”用户之间。您使用的公式根据所有投票中赞成的百分比对帖子进行排序。如果您还需要将更多支持的帖子放在更高的位置,您可以添加第二个排序参数,如下所示:.annotate( total_upvotes=Count('userUpVotes'), total_votes=Count('userUpVotes') / NullIf((Count('userUpVotes') + Count('userDownVotes')), 0) ).order_by(F('total_votes').desc(nulls_last=True), "-total_upvotes")
  • 我授予了赏金,因为它成功了一半。如果您仍然检查我在示例中给出的链接。它现在确实正确地对 6、1 进行了排名,但将 4/2 排名在 3/4 之下。
  • 您能附上该视图的完整代码吗?我相信这里还有其他问题。
  • 通过将 total_upvotes 更改为 total_upvotes=Count('userUpVotes')-Count('userDownVotes'), 使其工作
猜你喜欢
  • 2018-06-07
  • 2012-12-15
  • 2018-07-08
  • 1970-01-01
  • 1970-01-01
  • 2021-11-08
  • 2010-12-04
  • 2018-12-02
  • 2015-12-26
相关资源
最近更新 更多