我有要按日期显示的文章列表。每个用户都可以将任何文章标记为他的收藏夹。
如果用户已登录,那么他应该能够看到该文章是否已被标记为他最喜欢的一些指示。
以下是我的模型:
class Favourite(models.Model):
user = models.ForeignKey(User,on_delete=models.CASCADE)
date = models.DateTimeField(auto_now_add=True)
article = models.ForeignKey(Article, null=True,on_delete=models.CASCADE)
class Meta:
unique_together = ('user', 'article')
class Article(models.Model):
title = models.CharField(max_length=256)
intro_image = models.ImageField(null=True, blank=True, upload_to=doc_hash)
description = models.TextField(null=True, blank=True)
我在想每篇文章都要获取将文章标记为收藏夹的所有用户ID,然后在前端与当前用户一起检查它。
但是,如果某篇文章被 1000 个用户标记为最喜欢的文章,那么不必要地我将不得不获取 1000 个用户的数据以及该文章,这太多了。
有没有办法,如果我传递用户,我可以只获得每篇文章的该用户最喜欢的数据,这样我就可以保存查询和要传递到前端的数据量。
在视图的上下文中执行此操作,或作为自定义模板标记执行此操作。
下面的示例是干编码的,因此它们可能有愚蠢的错误。
在视图中(假设基于类的视图(:
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['is_favourite'] = Favourite.objects.filter(user=self.request.user, article=self.object).exists()
return context
用法:
{% if is_favourite %}Yay, you like it!{% endif %}
或模板标签:
@register.simple_tag(takes_context=True)
def is_favourite(context, article):
request = context['request']
return Favourite.objects.filter(user=request.user, article=article).exists()
用法:
{% is_favourite article as fav %}
{% if fav %}Yay, you like it!{% endif %}
编辑
对于ListView
,您可以执行以下操作
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['favourited_ids'] = set(Favourite.objects.filter(user=self.request.user, article__in=context['object_list']).values_list('article_id', flat=True))
return context
并使用它
{% if article.id in favourited_ids %}Yay, you like this article!{% endif %}
我假设你需要一个标志来说明用户是否已经将文章标记为收藏夹,假设有 100 篇文章,其中用户已将 40 篇文章标记为收藏夹,然后发送 100 篇文章数据,其中 40 篇文章的标志为读取 TRUE,其余为 FALSE。
以下是SQL等效项,您可以根据需要将其转换为Django ORM。"xyz">是您需要显示文章的用户 ID
SELECT article.*,
CASE
WHEN read.article_id IS NOT NULL then TRUE
ELSE FALSE
as read_flag
from Article as article
left join
(select article_id from Favourite where user_id = 'xyz') as read
on article.id = read.article_id
我从以下位置找到了以下答案:https://stackoverflow.com/a/51889455/2897115。使用批注和子查询。Django 使用我从中读取的注释和子查询可以更快。https://medium.com/@hansonkd/the-dramatic-benefits-of-django-subqueries-and-annotations-4195e0dafb16
我把给出的解决方案放在 https://stackoverflow.com/a/51889455/2897115。使用批注
qs = Post.objects.all() sub = Like.objects.filter(post__id=OuterRef('pk'), user=request.user) values = qs.annotate( date=Func(F('date'), function='db_specific_date_formatting_func'), current_user_like=Exists(sub) ).values('text, 'date', 'current_user_like')