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

Django模型IntegerField值加减后页面显示DeferredAttribute对象问题

问题原因

页面渲染出<django.db.models.query_utils.DeferredAttribute object at 0x...>的直接原因是视图中这行错误代码:

following_num = User.following_num

User.following_num是模型类层面的字段定义对象,不是某个用户实例的实际字段值,模板渲染类属性时就会输出这类对象信息。
原有代码另外存在三个逻辑问题:

  • 关注/取关触发的数值加减仅生成了局部变量,没有将更新结果写入数据库,页面刷新后数值会还原
  • 统计对象错位:代码取当前登录访问者的关注数,当作被访问主页用户的粉丝/关注数返回,统计逻辑完全错误
  • 先取值再加减的实现存在并发竞态问题,多用户同时操作时会出现计数不准的情况

修复方案

方案一(推荐):直接用多对多关系的count()统计,无需维护冗余字段

你的following多对多字段已经设置了related_name="followers",关联表会自动维护关注关系,直接调用count()就能拿到准确数值,完全不需要额外的following_num字段,从根源避免计数不一致问题。
修正后的视图函数代码:

from django.shortcuts import redirect

def username(request, user):
    # 获取被访问的主页用户
    profile_user = get_object_or_404(User, username=user)
    posts = Post.objects.filter(user=profile_user).order_by('-date_and_time')
    current_user = request.user

    # 访问自己的主页时不显示关注按钮
    followButton = profile_user != current_user

    if request.method == "POST":
        if "follow" in request.POST:
            current_user.following.add(profile_user)
        elif "unfollow" in request.POST:
            current_user.following.remove(profile_user)
        # 操作后重定向,避免表单重复提交
        return redirect("username", user=profile_user.username)

    # 直接通过多对多关系统计数量,永远和实际关注关系一致
    followers_count = profile_user.followers.count()
    following_count = profile_user.following.count()

    return render(request, "network/username.html",{
        "user": profile_user,
        "posts": posts,
        "followButton": followButton,
        "followers": followers_count,
        "following": following_count
    })

方案二:保留IntegerField计数字段的修复方式

如果一定要保留following_num字段做计数,需要注意更新时用F表达式做原子更新,更新后存库,且取值必须取实例的字段值,禁止直接引用类属性:

  1. 首先补全模型里缺失的粉丝数字段(原有模型只定义了关注数):
class User(AbstractUser):
    following = models.ManyToManyField("self", related_name="followers", symmetrical=False)
    following_num = models.IntegerField(default=0) # 本人关注的人数
    followers_num = models.IntegerField(default=0) # 本人的粉丝数
  1. 修正视图逻辑:
from django.db.models import F
from django.shortcuts import redirect

def username(request, user):
    profile_user = get_object_or_404(User, username=user)
    posts = Post.objects.filter(user=profile_user).order_by('-date_and_time')
    current_user = request.user

    followButton = profile_user != current_user

    if request.method == "POST":
        if "follow" in request.POST:
            current_user.following.add(profile_user)
            # 原子更新计数,避免竞态
            current_user.following_num = F('following_num') + 1
            profile_user.followers_num = F('followers_num') + 1
        elif "unfollow" in request.POST:
            current_user.following.remove(profile_user)
            current_user.following_num = F('following_num') - 1
            profile_user.followers_num = F('followers_num') - 1
        # 保存更新
        current_user.save()
        profile_user.save()
        # 重定向避免重复提交
        return redirect("username", user=profile_user.username)

    # 必须传实例的字段值,不能传User.following_num这类类属性
    return render(request, "network/username.html",{
        "user": profile_user,
        "posts": posts,
        "followButton": followButton,
        "followers": profile_user.followers_num,
        "following": profile_user.following_num
    })

修复验证

修改后模板不需要做任何调整,页面会正常渲染整数类型的关注/粉丝数,不会再出现DeferredAttribute的对象输出。关注/取关按钮点击后数值会正常更新,刷新页面也不会丢失。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 00:36:20