未读帖子 Django
Posted
技术标签:
【中文标题】未读帖子 Django【英文标题】:Unread posts Django 【发布时间】:2020-05-22 11:35:17 【问题描述】:我已经使用 Django(功能非常简单的博客)构建了一个博客,我希望能够在我的博客中只向用户显示他尚未阅读的帖子。 我有 10,000 多个帖子,我想在用户每次登录他还没有看到的随机帖子时向他展示/ 我是 Django 的新手,我不确定我应该以正确的方式去做。 我有 Post 模型:
class Post(models.Model):
author = models.ForeignKey('auth.User',on_delete=models.CASCADE)
title = models.CharField(max_length=200)
text = models.TextField()
created_date = models.DateTimeField(default=timezone.now)
published_date = models.DateTimeField(blank=True, null=True)
def publish(self):
self.published_date = timezone.now()
self.save()
def approve_comments(self):
return self.comments.filter(approved_comment=True)
def get_absolute_url(self):
return reverse("post_detail",kwargs='pk':self.pk)
def __str__(self):
return self.title
谢谢!
【问题讨论】:
显示已读帖子的User
和Post
之间的关系在哪里?只需添加(m2m 关系),然后通过排除已存在关系的帖子来过滤帖子。然后你需要选择随机帖子,解释here
@dirkgroten 我没有那种关系,因为这是我要求的——我问的是如何建立这种关系。谢谢!
【参考方案1】:
您必须记录用户以及他阅读了哪些帖子。就这样
class UserReadPost(models.Model):
user = models.ForeignKey(User, releated_name='user_read_posts')
post = models.ForeignKey(Post, releated_name='posts_read_by_users')
read_at = models.DateTimeField(auto_now=True)
每次用户阅读某个帖子时,您都必须在此表中添加一条记录。您可以像这样获取用户尚未阅读的所有帖子。
from django.db.models import OuterRef, Subquery, Exists
post_read_status = UserReadPost.objects.filter(post=OuterRef('post'), user=current_user_object)
Post.objects.all().annotate(has_read=Exists(post_read_status)).exclude(has_read=True).order_by('?')
这可以使用ManyToManyField
来完成,但添加您自己的表格将使您能够检查该用户何时阅读该特定帖子。
【讨论】:
请注意,order_by('?')
是一种非常低效的选择随机元素的方法。在大桌子上会很慢。请参阅this 以获得更有效的方法。如果您想要 5 个帖子,请对随机索引进行 5 次查询,这将比使用 order_by('?')
的一次查询要快。
@dirkgroten 我刚刚写了如何做到这一点。感谢开导。【参考方案2】:
你应该使用ManyToManyField:
class Post(models.Model):
author = models.ForeignKey('auth.User',on_delete=models.CASCADE)
title = models.CharField(max_length=200)
text = models.TextField()
created_date = models.DateTimeField(default=timezone.now)
published_date = models.DateTimeField(blank=True, null=True)
read_users = models.ManyToManyField(User) # Add this line
def publish(self):
self.published_date = timezone.now()
self.save()
def approve_comments(self):
return self.comments.filter(approved_comment=True)
def get_absolute_url(self):
return reverse("post_detail",kwargs='pk':self.pk)
def __str__(self):
return self.title
【讨论】:
以上是关于未读帖子 Django的主要内容,如果未能解决你的问题,请参考以下文章