You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django多对多反向查询:如何判断用户是否将院校加入心愿单

Django多对多关系反向存在性校验实现方案

问题根因

你当前的判断逻辑{% if data.student_set.all %}存在两个核心问题:

  • 校验维度错误:该逻辑是判断对应院校是否被任意学生加入过心愿单,未匹配当前登录用户的维度
  • 逻辑不合理:对QuerySet直接做if判断仅能校验是否存在数据,无法过滤指定用户的关联关系

实现步骤

前提约定

默认你的Student模型与Django内置User模型是一对一关联,即Student中存在字段user = models.OneToOneField(User, on_delete=models.CASCADE);如果你使用Student作为自定义用户模型,可直接替换下文的request.user.student为request.user。


方案1:视图层预查询(推荐,无N+1性能问题)

先在视图层一次性拉取当前用户的所有收藏院校ID,模板循环时直接做集合存在性校验,性能最优:

  1. 修改index视图代码:
def index(request):
    # 原变量名拼写错误,修正为复数universities
    universities = University.objects.filter(is_approved=True)
    user_wish_ids = set()
    # 用户登录才查询收藏数据
    if request.user.is_authenticated:
        user_wish_ids = set(
            request.user.student.wishlist.values_list('id', flat=True)
        )
    context = {
        'universities': universities,
        'user_wish_ids': user_wish_ids
    }
    return render(request, 'search/index.html', context)
  1. 调整模板判断逻辑:
{% for university in universities %}
<!-- 院校其他展示代码 -->
{% if university.id in user_wish_ids %}
    <button><em class="icon ni ni-heart-fill" ></em></button>
{% else %}
    <button><em class="icon ni ni-heart"></em></button>
{% endif %}
{% endfor %}

方案2:模板直接校验(适合数据量小的场景)

如果不想修改视图,也可以直接在模板中调用多对多字段的contains方法校验,但注意该方案会在每次循环时发起数据库查询,院校数量多的话会产生N+1性能问题:

{% for university in universities %}
<!-- 院校其他展示代码 -->
{% if request.user.student.wishlist.contains university %}
    <button><em class="icon ni ni-heart-fill" ></em></button>
{% else %}
    <button><em class="icon ni ni-heart"></em></button>
{% endif %}
{% endfor %}

反向查询的正确写法

如果你一定要用反向关联student_set实现,写法如下,同样存在N+1性能问题:

{% if university.student_set.filter(id=request.user.student.id).exists %}
<!-- 实心红心逻辑 -->
{% else %}
<!-- 空心心逻辑 -->
{% endif %}

内容的提问来源于stack exchange,提问作者sixovov947

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 01:48:04