I currently have a post that has upvotes and downvotes.
the model looks something like this
class Word(models.Model):
name = models.CharField(max_length=250)
upvotes = models.ManyToManyField(User, blank=True, related_name='threadUpVotes')
downvotes = models.ManyToManyField(User, blank=True, related_name='threaddDownVotes')
in my views.py I have so far gotten this far
from django.db.models import F, Sum
words = Word.objects.filter(name__iexact='test').annotate(
total_votes=Sum(F('upvotes') + F('downvotes'))).order_by('total_votes')
But I'm unsure what to do next to get it to rank by say the one with most upvotes vs downvotes.
You ham many to many field, You should use:
from django.db.models import F, Sum, Count
words = Word.objects.filter(name__iexact='test').annotate(
total_votes=Count('upvotes') - Count('downvotes')).order_by('-total_votes')
or in your answer:
from django.db.models import F, Sum, Count
from django.db.models.functions.comparison import NullIf
words = Word.objects.filter(name__iexact='test').annotate(
total_votes=Count('upvotes') / NullIf(
Count('upvotes') + Count('downvotes')
)).order_by('-total_votes')
I realized after I posted, I sumply had to divided the upvotes by the total number of votes and order in reverse.
words = Word.objects.filter(name__iexact='test').annotate(
total_votes=Sum(F('upvotes'))/Sum(F('upvotes') + F('downvotes'))).order_by('-total_votes')
You can make use of aCount
expression [Django-doc] with distinct=True
[Django-doc] , otherwise you will count an upvote as many times there are downvotes and vice versa. We thus can determine the share of upvotes with:
from django.db.models import Count
words = Word.objects.filter(
name__iexact='test'
).annotate(
total_votes=Count('upvotes', distinct=True) / (Count('upvotes', distinct=True) + Count('downvotes', distinct=True))
).order_by('total_votes')
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.