Django模板访问queryset判断用户已开始当前模块写法失效问题
问题原因
原模板判断逻辑无法生效,是三个写法错误导致的:
request.user.progression_set.all返回的是Progression模型的对象查询集(QuerySet),不是单个进度实例,直接在后面拼接.started_module属于非法调用,只有单个Progression实例才有started_module外键属性。- 你已经在模型Meta里配置了
user和started_module的联合唯一约束,意味着一个用户对同一个模块最多只会产生一条进度记录,不需要用in做集合遍历判断。 - 需要展示的普通提示文本不需要包裹在
{{ }}变量标签中,{{ }}仅用来渲染后端传入的变量,普通文本直接写在模板里即可。
解决方法
方案1:视图层预处理(推荐)
把判断逻辑放在视图里提前计算,既能减少模板层的逻辑复杂度,也能避免模板里重复查库的性能问题:
def Module_Detail(request,module_slug): module = get_object_or_404(Module,slug=module_slug) has_started = False # 先校验用户登录状态,匿名用户不存在关联进度数据 if request.user.is_authenticated: has_started = Progression.objects.filter( user=request.user, started_module=module ).exists() context = { 'module' : module, 'has_started': has_started } return render(request,'courses/module-detail.html',context)
模板中直接调用预处理好的变量即可:
{% if has_started %} <p>你已经开始学习这个模块</p> {% endif %}
方案2:模板层直接判断
如果不想修改视图代码,也可以直接在模板中写合法的ORM查询判断,注意处理匿名用户场景:
{% if request.user.is_authenticated and request.user.progression_set.filter(started_module=module).exists %} <p>你已经开始学习这个模块</p> {% endif %}
注意:Django模板中调用无参数的对象方法不需要加括号,直接写
.exists即可,不要写成Python语法里的.exists()。
额外优化建议
你模型里的completedchapters字段不符合Python蛇形命名规范,建议改成completed_chapters,避免后续维护出现命名混淆问题。
内容的提问来源于stack exchange,提问作者NAS
相关产品推荐
相关产品推荐

