Django一对多查询为何报‘object has no attribute 'exclude'’错误?
错误原因分析
报错'ReverseManyToOneDescriptor' object has no attribute 'exclude'的核心问题是:你直接通过Profile模型类调用skill_set,但skill_set是Django为一对多反向关联生成的实例属性——它只能绑定到具体的Profile对象上使用,不能直接用在模型类本身。
此外代码还有两处细节问题:
- 变量名不统一:定义的
topSkill/otherSkill在context中误写为topSkills/otherSkills - 无描述技能的查询写法错误:
Profile.skill_set(description = "")不符合Django ORM的语法规范
修正后的视图代码
def user_profile(request,pk): profileObj = Profile.objects.get(id = pk) # 用具体的profile实例调用skill_set,筛选有有效描述的技能 topSkills = profileObj.skill_set.exclude(description__isnull=True).exclude(description__exact='') # 筛选无描述的技能(包含描述为null或空字符串的情况) otherSkills = profileObj.skill_set.filter(description__isnull=True) | profileObj.skill_set.filter(description__exact='') # 也可以用更简洁的Q查询(需提前导入from django.db.models import Q) # otherSkills = profileObj.skill_set.filter(Q(description__isnull=True) | Q(description__exact='')) context = {"profile":profileObj,'topSkills':topSkills,"otherSkills":otherSkills} return render(request, 'users/user_profile.html', context)
可选优化建议
如果你觉得skill_set这个名称不够直观,可以在Skill模型的owner字段中自定义反向关联名称:
class Skill(models.Model): owner = models.ForeignKey(Profile,null=True, blank=True, on_delete=models.CASCADE, related_name='skills') # 其他字段保持不变
之后就可以用profileObj.skills代替profileObj.skill_set,代码可读性会更强。
内容的提问来源于stack exchange,提问作者Royalty
相关产品推荐
相关产品推荐

