1

I have the following models

class Dishes(models.Model):
    name = models.CharField(max_length=40, unique=True)
    date_added = models.DateTimeField(auto_now_add=True)
    #increment/decrement with upvote added or removed
    count_votes = models.IntegerField(blank=True, null=True, default=0)

class Upvotes(models.Model):
    dish = models.ForeignKey(Dishes)
    user = models.ForeignKey(User)
    date_added = models.DateTimeField(auto_now_add=True)

I have 3 sorts for dishes, the first 2 are by date_added & count_votes, which are easy to implement with dishes.order_by('-count_votes') and dishes.order_by('-date_added'), the third sort is a "trending sort" which I essentially want to be a sort that ranks dishes as a function of upvotes over time, any idea how I could go about doing this?

Tikue Anazodo
  • 319
  • 1
  • 2
  • 10
  • can it not be `Dishes.objects.order_by('upvotes')` and in `Upvotes`, specify `class Meta: ordering = ('date_added', )` – karthikr Sep 30 '13 at 01:17
  • That still just sorts by total number of upvotes descending. The idea would be that something with 10 votes within the last hour and 10 total votes would be higher in the the 'tending sort' than something with 2 upvotes in the last hour and a total of 100 upvotes – Tikue Anazodo Sep 30 '13 at 01:27

1 Answers1

1

Sounds like you're looking to implement a "Trending" algorithm.

There are plenty of articles on the subject, and you're not the first to ask about this. check out this and this, and definitly look into using some pre-built package, I've found django-trending and django-voting which might be helpful to you.

Edit

Django allows complex ordering by using annotate, but that is limited to built-in aggregation functions such as Avg, Sum and so on (you can read about how here). So there is no django-specific way to order using a custom method.

However, that doesn't mean you can't do it with python:

sorted(Dishes.objects.all(), key=lambda x: x.trending_method())

I can't say how it will fare with a large database, but this is the only way I know other than using raw SQL (which is also an optional, though wearying solution). Hope that helps!

Community
  • 1
  • 1
yuvi
  • 18,155
  • 8
  • 56
  • 93
  • It's really not so much the algorithm as it is that I don't know how to implement it in Django models. I'm using a variation of the Hackernews algo ( (p - 1) / (t + 2)^1.8) , where p is upvotes and t is age in hours, I can do this normally in SQL, but I don't understand how to implement it in my django model – Tikue Anazodo Sep 30 '13 at 18:02
  • Btw I know about django-trending and django-voting, I would rather implement my trending algo by myself in my model – Tikue Anazodo Sep 30 '13 at 18:03
  • So if I understand you correctly, you already have a method for this and you just want to sort according to it, right? – yuvi Sep 30 '13 at 19:07
  • Yes that is correct, I have written a trending method, I am just not sure how to fit it into my django model so that I can call an 'order by' on it – Tikue Anazodo Oct 01 '13 at 00:08
  • 1
    Then what you're looking for is using annotate, which clause can be used for order_by. However I'm not entirely sure how to make that work with a custom method. I promise I'll try finding a solution, in the meantime read about it here: https://docs.djangoproject.com/en/dev/topics/db/aggregation/ – yuvi Oct 01 '13 at 02:12