0

i'm using django 2 and in my list view i want to oder the queryset by likecount and datetime field. The main goal is to odering the post with mostlikes for today. Like, i want to show the most liked posts for today. It's like todays top 10 post(mostliked). i have tried many ways but can't figure it out. I hope you guys can help me.

My models.py:

class post(models.Model):
    parent = models.ForeignKey("self", on_delete=models.CASCADE, blank=True, null=True)
    title = models.CharField(max_length=100)
    image = models.ImageField(upload_to='post_pics', null=True, blank=True)
    content = models.TextField()
    likes = models.ManyToManyField(User, related_name='likes', blank=True)
    date_posted = models.DateTimeField(default=timezone.now)
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    restrict_comments = models.BooleanField(default=False)
    watchlist = models.ManyToManyField(User, related_name='watchlist', blank=True)

    def __str__(self):
        return self.content

    class Meta:
        ordering = ['-date_posted', 'title']

    def get_absolute_url(self):
        return reverse ('blog-home')

    def total_likes(self):
        return self.likes.count()

My views.py:

@login_required
def most_likes(request):
    posts = post.objects.annotate(like_count=Count('likes')).order_by('-like_count', '-date_posted')
    context = {'posts': posts}

    return render(request, 'blog/most_likes.html', context)
Flux
  • 9,805
  • 5
  • 46
  • 92
  • 2
    Everything looks good at first sight. What's the output you're currently getting like? – revliscano May 01 '20 at 20:08
  • Its giving the most liked post by dates. Like if my post is 5 months old and recent it gets top likes it returns the post on top. Like, the top liked post remain on the top forever if no one exceeded the likes count of the current post. I want to order it for 24hours. It will return the topliked posts in 24 hours of time. @revliscano – Cavin blake May 02 '20 at 05:17

1 Answers1

0

If I'm getting you right, you are already ordering your queryset by the fields you want (like_count and date_posted), but you're still missing the part of getting only the results for a desired time period.

If this is the case, then what you're missing is to filter the queryset. You would need something like this (to get the posts of the last 10 days, ordered by their date and likes count):

import datetime as dt


@login_required
def most_likes(request):
    delta = dt.timedelta(days=10)
    posts = post.objects.filter(date_posted__gt=(dt.datetime.now() - delta)) \
        .annotate(like_count=Count('likes')).order_by('-like_count', '-date_posted')
    context = {'posts': posts}

    return render(request, 'blog/most_likes.html', context)

Now, I would try to pass the value of the desired time period I want to filter the data as a query parameter, so I can do something as the following:

delta = dt.timedelta(days=request.GET.get('days'))
revliscano
  • 2,227
  • 2
  • 12
  • 21
  • I didn't understand the last part the query parameter part. in the last part you didn't mention the number of days. @revliscano – Cavin blake May 02 '20 at 19:14
  • Yes, I mean, I'm only suggesting you that you might consider passing that number of days as a query parameter to that view @Cavinblake – revliscano May 02 '20 at 20:02
  • thank you everything seems to working ok. but a datetime warning raises `2020-05-02 19:43:59,467: /home/neso/.virtualenvs/django2/lib/python3.6/site-packages/django/db/models/fields/__init__.py:1421: RuntimeWarning: DateTimeField post.date_posted received a naive datetime (2020-04-22 19:43:59.466748) while time zone support is active. 2020-05-02 19:43:59,467: RuntimeWarning) ` this is the warning i'm getting. otherwise everything is working – Cavin blake May 02 '20 at 20:26
  • Yes, that's because `datetime.now()` doesn't have the timezone information, but your `date_posted` field expects it. It should not be a problem in most use cases, but if you want more information about how to pass that timezone info, you can check the answers to this question: https://stackoverflow.com/questions/2331592/why-does-datetime-datetime-utcnow-not-contain-timezone-information – revliscano May 02 '20 at 21:55
  • And if i don't pass the number of days in the query parameter. I mean if i don't add the last line of query parameter instead i'm using only ** delta = dt.timedelta(days=10) ** this line. Would it cause any problem? @revliscano – Cavin blake May 03 '20 at 05:12
  • No, it wouldn't cause any problem, but are you going to always want to get only the top posts for the last 10 days? I just suggested that so that it can be dynamically set. @Cavinblake – revliscano May 03 '20 at 05:29
  • yeah top post for the last 10 days. But that code works ok. It is giving me the top posts of last 10 days only. @revliscano – Cavin blake May 03 '20 at 07:46
  • and if i replace the `delta = dt.timedelta(days=10) ` with the query parameter `delta = dt.timedelta(days=request.GET.get('10'))` it is giving me errors its says `unsupported type for timedelta days component: NoneType` @revliscano – Cavin blake May 03 '20 at 07:56
  • Okay Cavin you are just not getting the point of the query parameters, right? Actually you don't seem to know how to use them, so for now don't overcomplicate things and let everything preset to 10 days. If you ever get to one point where you want to let users be able to get the top posts for 1 day, 10 days, 1 month, 1 year, etc, then you can take back my suggestion and apply it. P.S: the error you're getting is because you are not passing any query parameter with key='10', so instead you're getting None. Again, forget about that line and keep everything as it is working now. – revliscano May 03 '20 at 17:05
  • Okay. I keep everything as it is working now. Thank you. – Cavin blake May 04 '20 at 14:27
  • Yes, my friend. Good luck with your project! – revliscano May 04 '20 at 17:54
  • Thank you so much. – Cavin blake May 05 '20 at 15:50