Django模型保存时修改ManyToManyField触发递归错误求助
Django保存Profile模型时递归错误的解决方法
问题根源
你的代码触发RecursionError是因为在save方法内部再次调用了self.save(),这会导致无限递归调用,直到超出Python的递归深度限制。此外,硬写好友数量的逻辑也不够灵活,后续修改类型对应的人数时需要改动代码。
解决方案
- 移除递归调用:修改
ManyToManyField的关联关系不需要额外调用模型的save()方法,Django会自动处理关联表的更新,直接调用父类的save()即可。 - 动态获取最大好友数:用字典存储各Profile类型对应的最大好友数,避免硬编码,提升代码可维护性。
修正后的完整代码
# 直接存储各类型允许的最大好友数,逻辑更直观 MAX_FRIENDS_FOR_TYPE = {"X": 10, "Y": 20} class ProfileType(models.TextChoices): X = "X", "x" Y = "Y", "y" # 原代码默认值为ProfileType.BASIC,但未定义,这里补充或调整为已有类型 BASIC = "X", "x" class Profile(models.Model): type = models.TextField(choices=ProfileType.choices, default=ProfileType.BASIC, max_length=1) friends = models.ManyToManyField(User, blank=True, related_name="friends") __currently_type = None def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.__currently_type = self.type def save(self, *args, **kwargs) -> None: # 检查Profile类型是否降级(新类型允许的好友数更少) if self.type != self.__currently_type: old_max = MAX_FRIENDS_FOR_TYPE[self.__currently_type] new_max = MAX_FRIENDS_FOR_TYPE[self.type] if new_max < old_max: # 获取超出新上限的好友列表 excess_friends = self.friends.all()[new_max:] if excess_friends.exists(): self.friends.remove(*excess_friends) # 调用父类方法保存模型本身的字段更新 super().save(*args, **kwargs) # 更新类型缓存,用于下次保存时对比 self.__currently_type = self.type
关键修改说明
- 替换
POWER_OF_PROFILE_TYPE为MAX_FRIENDS_FOR_TYPE,直接映射类型与最大好友数,逻辑更清晰 - 删除了引发递归的
self.save()调用 - 修正了原代码中未定义的
type_of_profile属性,直接使用self.type - 增加
excess_friends.exists()判断,避免对空列表执行无意义的移除操作
内容的提问来源于stack exchange,提问作者Mateusz
相关产品推荐
相关产品推荐

