Reputation: 153
I want to order my query based on the number of upvotes but I can't figure out how to do it. It seems way too complex! ( btw am I over-complicating things?)
so here is my models.py
class Activity(models.Model):
FAVORITE = 'F'
LIKE = 'L'
UP_VOTE = 'U'
DOWN_VOTE = 'D'
FOLLOW = 'W'
REPORT = 'R'
ACTIVITY_TYPES = (
(FAVORITE, 'Favorite'),
(LIKE, 'Like'),
(UP_VOTE, 'Up Vote'),
(DOWN_VOTE, 'Down Vote'),
(FOLLOW, 'Follow'),
(REPORT, 'Report')
)
user = models.ForeignKey(User)
activity_type = models.CharField(max_length=1, choices=ACTIVITY_TYPES)
date = models.DateTimeField(auto_now_add=True)
# Below the mandatory fields for generic relation
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey()
class Entry(models.Model):
text = models.TextField(default='')
time_created = models.DateTimeField(auto_now=False, auto_now_add=True)
time_updated = models.DateTimeField(auto_now=True, auto_now_add=False)
created_by = models.ForeignKey(User, on_delete=models.CASCADE)
class Meta:
abstract = True
class QuestionManager(models.Manager):
def by_topic(self, topic):
...
def by_recent(self):
...
def by_upvote_count(self):
return self.all().order_by('-upvotes')[:5]\
.select_related('created_by','created_by__userprofile')\
.prefetch_related('question_comments','question_comments__reply',)
class Question(Entry):
objects = models.Manager()
get = QuestionManager()
activities = GenericRelation(Activity, related_query_name='questions')
def calculate_votes(self, type):
return self.activities.filter(activity_type=type).count()
up_votes = property(calculate_votes, 'U')
down_votes = property(calculate_votes, 'D')
so, what I'm trying to do is to get by_upvote_count to return the top 5 upvoted items.
I found the Count() method of the django.db.models but could get it to work with my set up, I want to do something like this:
Question.objects.all().annotate(q = Count(activities__activity_type='U')).order_by('-q')
but obviously this doesn't work.
Upvotes: 0
Views: 45
Reputation: 153
Ok, so after reading a bunch of articles and some questions in stackoverflow, I finally found a working answer, here it goes:
from django.db.models import Case,When
Question.objects.all()\
.annotate(upvotes=Count(
Case(
When(activities__activity_type='U', then=1)
), distinct=True
)).order_by('-upvotes')[:5]
Using Case, and When you can do conditionals in your queries.
Upvotes: 1
Reputation: 27523
you can do something like this
Model.objects.filter(activity_type='U').annotate(q_count=Count('activity_type')).order_by('-q_count')[:5]
Upvotes: 1