Django模板中无法判断当前用户是否收藏分页Recipe的问题
问题分析与解决
1. 拼写错误导致的基础问题
你的Recipe模型里多对多字段叫favourites(英式拼写),但模板里写的是recipe.favorites(美式拼写),这是第一个直接错误,先修正这个拼写问题。
2. 多对多字段的模板判断逻辑问题
即使修正拼写,recipe.favourites是Django的多对多管理器对象,不能直接用request.user.profile.id in recipe.favourites来判断,因为管理器不是可迭代的ID集合。你可以用以下两种方法解决:
方法一:模板内直接判断(适合简单场景,注意性能)
修正拼写后,直接判断用户profile是否在recipe.favourites.all()的结果集中:
{% for recipe in page_obj %} {% if request.user.profile in recipe.favourites.all %} <button>Recipe added to favourites</button> {% else %} <button>Add to favourites</button> {% endif %} {% endfor %}
⚠️ 注意:这种方法会对每个Recipe发起额外查询,分页数据较多时会有性能损耗。
方法二:视图中用annotate预计算(推荐,无N+1查询问题)
在ListView的get_queryset里,用Exists子查询提前标注当前用户是否已收藏该食谱,模板直接使用预计算的字段即可:
先导入所需模块:
from django.db.models import Exists, OuterRef
修改你的ListView代码:
class Home(ListView): model = Recipe template_name = 'home.html' paginate_by = 2 def get_queryset(self): queryset = Recipe.objects.order_by('id').prefetch_related('profile__recipecomment_set__recipe') # 仅当用户登录时,添加收藏状态标注 if self.request.user.is_authenticated: user_profile = self.request.user.profile queryset = queryset.annotate( is_favourite=Exists( Recipe.favourites.through.objects.filter( recipe_id=OuterRef('pk'), profile_id=user_profile.pk ) ) ) return queryset
然后模板里直接判断预计算的字段:
{% for recipe in page_obj %} {% if user.is_authenticated %} {% if recipe.is_favourite %} <button>Recipe added to favourites</button> {% else %} <button>Add to favourites</button> {% endif %} {% else %} <button>请登录后收藏</button> {% endif %} {% endfor %}
这种方法只会发起2次查询(一次获取Recipe列表,一次子查询判断所有食谱的收藏状态),性能更优,适合分页场景。
内容的提问来源于stack exchange,提问作者Spica Simpson
相关产品推荐
相关产品推荐

