Django自引用多对多关系场景下无法正确获取关联数据如何解决
问题原因
- 关联属性调用错误:
to_person是Relationship模型中指向被关注用户的外键的反向关联,代表的是所有关注当前用户的关联记录,你在当前用户对象上直接调用self.to_person拿到的是反向关系管理器,根本不是你要的当前用户关注的其他人列表,所以输出为空。 get_all_followings方法没有设置返回值,视图中拿到的all_followings默认就是None。- 自关联多对多字段未指定
through_fields:自关联场景下使用中间表必须指定through_fields明确字段对应关系,否则多对多的方向会异常。 - 额外错误:你自定义了
password字段覆盖了AbstractUser自带的密码字段,设置的max_length=15远小于Django加密后密码的长度,会导致密码存储失败,后续登录逻辑会直接报错。
解决步骤
- 修正
CustomUser模型的定义,补全多对多字段参数,删除多余的自定义password字段:
class CustomUser(AbstractUser): email = models.EmailField(max_length=250, null=False, unique=True) name = models.CharField(max_length=50, null=False) username = models.CharField(max_length=50, null=False) # 删掉自定义的password字段,用父类自带的即可 # 补全through_fields参数,第一个是源模型对应的外键,第二个是目标模型对应的外键 # 字段名改为following语义更清晰,避免混淆 following = models.ManyToManyField('self', through='Relationship', symmetrical=False, related_name='followers', through_fields=('from_person', 'to_person')) USERNAME_FIELD = 'email' REQUIRED_FIELDS = ['name', 'username'] def get_all_followings(self): # 直接通过多对多字段拿到所有关注的用户 return self.following.all()
- 修正视图代码,拿到关注列表后传入模板:
def see_all_followings(request): if request.method == 'GET': # request.user本身就是CustomUser实例,不需要额外查库 all_followings = request.user.get_all_followings() return render(request, "all_followings.html", {'users': all_followings, 'is_follow': True})
- 执行迁移命令更新数据库结构:
python manage.py makemigrations python manage.py migrate
如果之前已经有错误的迁移记录,需要先清空对应app的migrations文件夹下除了__init__.py之外的文件,再重新生成迁移。
内容的提问来源于stack exchange,提问作者Atharva
相关产品推荐
相关产品推荐

