Django order by count by date
Доброе утро!
Я перепробовал много способов, но не могу добиться упорядочивания постов по лайкам и по дате. Например, я хочу иметь страницу "популярный пост", которая содержит только посты за сегодня, но упорядоченные по наиболее понравившимся.
Вот мои модели:
Class Post(models.Model):
name = models.CharField(max_length=40, default=None, null=False)
cover = models.CharField(max_length=100, default=None, null=True, blank=True)
content = models.TextField(max_length=2000, default=None, null=False)
class VoteDate(models.Model):
post = models.ForeignKey(Post, on_delete=models.CASCADE)
date = models.DateTimeField(default=timezone.now)
Ближе всего я подошел, но ничего не получилось, вот эта строка:
hot_today = Post.objects.annotate(count=Count('votedate', filter=Q(votedate__date=datetime.today()))).order_by('count')[:30]
Спасибо за помощь!
Здесь есть две проблемы: (1) вы фильтруете по полю date объектов VoteDate, которое является DateTime, следовательно, фильтрация не будет работать правильно, поскольку вы сравниваете объект datetime с объектом datetime с часами, минутами и секундами, установленными на ноль; и (2) вы должны упорядочивать в порядке убывания, поэтому -count, а не count:
from django.db.models import Q
from django.utils.timezone import now
hot_today = Post.objects.annotate(
count=Count('votedate', filter=Q(votedate__date__date=now().date()))
).order_by('-count')[:30]
Возможно, вы захотите добавить индекс базы данных на поле date для повышения эффективности, и фильтровать в поле QuerySet:
class VoteDate(models.Model):
post = models.ForeignKey(Post, on_delete=models.CASCADE)
date = models.DateTimeField(auto_now_add=True, db_index=True)
мы можем фильтровать с помощью:
from django.db.models import Q
from django.utils.timezone import now
hot_today = Post.objects.filter(
votedate__date__date=now().date()
).annotate(
count=Count('votedate')
).order_by('-count')[:30]
Это не покажет Post, у которых нет голосов в этот день, но это может не быть проблемой. Фильтрация позволит эффективно сократить время запроса до только VoteDate, установленных на этот день.