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
, установленных на этот день.