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.
CodePudding user response:
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')
CodePudding user response:
You can make use of a Count
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')
CodePudding user response:
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
words = Word.objects.filter(name__iexact='test').annotate(
total_votes=Count('upvotes') / (Count('upvotes') Count('downvotes'))).order_by('-total_votes')