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

Django+DRF如何正确获取中间模型对应当前用户的关联对象

问题原因
  • 你定义的user_skills是Skill模型指向UserSkill的一对多反向关联,默认序列化该字段时,会返回当前Skill关联的所有UserSkill记录,不会自动按当前请求用户做过滤,因此会带出其他用户的关联数据。
  • 你的查询代码存在拼写错误:跨关联查询字段应使用双下划线连接关联名与字段名,user_skills_user__disabled的正确写法为user_skills__disabled,原写法会触发字段不存在的报错。
正确实现方案

通过Django ORM提供的Prefetch对象提前过滤反向关联的数据集,同时修改序列化器返回过滤后的单条中间表记录,全程不会产生额外SQL性能损耗,也不会返回无关数据。

1. 修改ViewSet查询逻辑

from django.db.models import Prefetch
from rest_framework import viewsets, permissions
from .models import Skill, UserSkill
from .serializers import AssignedSkillSerializer

class AssignedSkillViewSet(viewsets.ModelViewSet):
    serializer_class = AssignedSkillSerializer
    permission_classes = [permissions.IsAuthenticated]

    def get_queryset(self):
        current_user = self.request.user
        # 定义过滤规则:只取当前用户、未禁用的中间表记录
        matched_user_skill_qs = UserSkill.objects.filter(
            user=current_user,
            disabled=False
        )
        return Skill.objects.filter(
            user_skills__user=current_user,
            user_skills__disabled=False
        # 预加载过滤后的中间表数据,挂载到自定义属性上,避免返回全量关联记录
        ).prefetch_related(
            Prefetch(
                'user_skills',
                queryset=matched_user_skill_qs,
                to_attr='current_user_skill'
            )
        ).distinct()

说明:因为查询Skill时已经加了「关联当前用户、未禁用的UserSkill」的过滤条件,每个返回的Skill对象对应的current_user_skill属性中,只会存在0或1条匹配的UserSkill记录,不会出现多条结果。

2. 修改序列化器

先定义中间模型的精简序列化器,再替换原来全量返回的user_skills字段:

from rest_framework import serializers
from .models import Skill, UserSkill

# 中间模型序列化器,按需配置返回字段即可
class UserSkillBriefSerializer(serializers.ModelSerializer):
    class Meta:
        model = UserSkill
        fields = ['id', 'disabled'] # 可自行添加需要返回的UserSkill字段

class AssignedSkillSerializer(serializers.HyperlinkedModelSerializer):
    # 直接返回预加载好的当前用户对应的中间表记录
    current_user_skill = UserSkillBriefSerializer(read_only=True)

    class Meta:
        model = Skill
        fields = [
            'id',
            'url',
            'title',
            'description',
            'current_user_skill',
        ]
方案优势
  • 不会返回其他用户的关联数据,完全符合需求
  • 借助prefetch_related避免了N+1查询问题,性能和原生关联查询一致
  • 不需要对返回列表做取下标、排序等不可靠操作,结果稳定

内容的提问来源于stack exchange,提问作者Andrés Root

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.01 01:09:24