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

Django创建关注关系后,User关联followers/followings集合为空问题

问题:Django关注关系中反向关联集合为空的排查

我正在开发支持用户互相关注的社交媒体项目,相关模型如下:

django.contrib.auth.models.User
class UsersProfiles(ddm.Model):
    user = ddm.OneToOneField(
        dcam.User,
        on_delete=ddm.CASCADE,
        related_name="profile",
    )
    followers_count = ddm.IntegerField(default=0)
    followings_count = ddm.IntegerField(default=0)
class UsersFollows(ddm.Model):
    follower = ddm.ForeignKey(
        dcam.User,
        on_delete=ddm.CASCADE,
        related_name="followers",
    )
    following = ddm.ForeignKey(
        dcam.User,
        on_delete=ddm.CASCADE,
        related_name="followings",
    )

为提升扩展性,我通过存储粉丝数和关注数实现数据冗余,而非通过UsersFollows模型计算。使用Django事务保证添加关注操作的原子性:

with ddt.atomic():
    umuf.UsersFollows.objects.create(
        follower=user,
        following=followed_user,
    )
    followed_user.profile.followers_count += 1
    user.profile.followings_count += 1
    followed_user.profile.save()
    user.profile.save()

但测试时发现用户对应的粉丝和关注集合为空:

def test_valid(self):
    response = self.client.post(
        c.urls.USERS_1_FOLLOWINGS,
        {"user": 2},
        headers=h.generate_headers(self.login_response),
    )
    h.assertEqualResponses(response, c.responses.SUCCESS)
    user1 = dcam.User.objects.get(pk=1)
    user2 = dcam.User.objects.get(pk=2)
    self.assertEqual(user1.profile.followings_count, 1)
    self.assertEqual(user2.profile.followers_count, 1)
    follow = umuf.UsersFollows.objects.filter(
        follower=user1,
        following=user2,
    )
    self.assertEqual(len(follow), 1)
    # 以下两个断言失败
    self.assertIn(user1, user2.followers.all())
    self.assertIn(user2, user1.followings.all())

我尝试保存两个User实例,也尝试手动保存UsersFollows实例,但问题仍未解决,请问遗漏了什么?


解决方案

问题出在UsersFollows模型的related_name命名逻辑完全搞反了:

  • related_name的作用是定义反向关联的名称,也就是从关联模型(这里是User)访问当前模型(UsersFollows)记录的属性名。
  • 你当前的设置中,follower字段的related_name="followers",意味着user.followers.all()会返回所有以该user为关注者的UsersFollows记录,而不是你期望的「关注该user的人」。
  • 同理,following字段的related_name="followings",会让user.followings.all()返回所有被该user关注的UsersFollows记录的反向?完全不符合你的语义需求。

正确的related_name应该对应业务语义:

  • 对于follower字段(发起关注的用户),反向关联应该是「该用户关注的所有人」,所以related_name设为followings。
  • 对于following字段(被关注的用户),反向关联应该是「所有关注该用户的人」,所以related_name设为followers。

修正后的UsersFollows模型:

class UsersFollows(ddm.Model):
    follower = ddm.ForeignKey(
        dcam.User,
        on_delete=ddm.CASCADE,
        related_name="followings",  # user.followings → 该用户关注的所有人
    )
    following = ddm.ForeignKey(
        dcam.User,
        on_delete=ddm.CASCADE,
        related_name="followers",  # user.followers → 所有关注该用户的人
    )

修正后,你的测试断言就能正常通过:

  • user2.followers.all()会返回所有关注user2的用户(即user1)
  • user1.followings.all()会返回user1关注的用户(即user2)

另外不需要额外保存User实例,因为反向关联的数据是直接从UsersFollows表中查询的,只要记录创建成功,重新查询User实例后就能获取到正确的关联集合。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 06:33:24