Django双外键关联User时反向查询message_set报错是什么原因?
问题原因及解决方法
你猜测的原因是正确的,该错误确实由Message表存在两个指向User模型的外键,且你自定义了外键的related_name参数导致。
错误根源
Django 默认会为外键生成反向关联属性,命名规则为小写模型名_set,但如果同一模型存在多个指向同一关联表的外键,你必须为每个外键指定独立的related_name,此时默认的*_set命名会被你自定义的related_name覆盖,不再生效。
你当前的Message模型中:
sender外键的related_name设为了sender,对应User实例查询自己发送的所有消息,需调用user.sender.all()receiver外键的related_name设为了receiver,对应User实例查询自己接收的所有消息,需调用user.receiver.all()
你代码中调用的user.message_set.all()本身不存在,同时回溯信息显示你还误写为messages_set(多了字母s),这两个问题共同触发了属性不存在的报错。
修正方案
临时适配现有模型
如果你暂时不想修改模型定义,直接替换查询语句即可:
# 查询用户发送的所有消息 user.sender.all() # 查询用户接收的所有消息 user.receiver.all() # 如需查询该用户关联的所有收发消息,可合并查询集 from itertools import chain all_user_messages = list(chain(user.sender.all(), user.receiver.all())) # 按消息创建时间排序 all_user_messages.sort(key=lambda x: x.created_on)
优化命名(推荐)
当前的related_name命名语义模糊,很容易混淆,建议修改模型字段定义后执行迁移:
class Message(models.Model): sender = models.ForeignKey(User, on_delete=models.CASCADE, related_name="sent_messages") receiver = models.ForeignKey( User, on_delete=models.CASCADE, related_name="received_messages" ) text = models.CharField(max_length=2000) created_on = models.DateTimeField(auto_now=True)
修改后查询逻辑更清晰,不易出错:
# 查询用户发送的消息 user.sent_messages.all() # 查询用户接收的消息 user.received_messages.all()
内容的提问来源于stack exchange,提问作者neeraj lamsal
相关产品推荐
相关产品推荐

