【问题标题】:Django model with 2 foreign keys from the same table具有来自同一个表的 2 个外键的 Django 模型
【发布时间】:2010-10-09 15:49:36
【问题描述】:

我想要一个 Django 模型,它具有来自同一个表的 2 个外键。这是一个事件表,有 2 列供员工使用:“演员”和“接收者”。但我得到这个错误:

错误:一个或多个模型未验证:tasks.task:中介 模型 TaskEvent 对 Employee 有多个外键,即 模棱两可,是不允许的。

有没有更好的建模方法?

我想我要添加一个TaskEvent_to_Employee 表。其中将有两条记录,一条用于与每个TaskEvent 相关的两名员工中的每一个。有谁知道更简单的解决方法?

【问题讨论】:

标签: django foreign-keys ambiguity


【解决方案1】:

我还没有这样做,但我使用 inspectdb 从现有的数据库中生成 models.py 文件,该文件正是这样做的 - 这是 inspectdb 退回的,所以它应该可以工作:

creator = models.ForeignKey(Users, null=True, related_name='creator')
assignee = models.ForeignKey(Users, null=True, related_name='assignee')

希望这对你有用 - 如果不是我也会有问题。

【讨论】:

  • Related_name 不是使用“related_name”返回包含属性的模型的链接,因此在上面的示例中,您不会将related_name 更改为“createe”和“assignor”,因为如果有人在您的示例中访问对象“受让人”,他们将获得“受让人”?
  • 这是推荐的方法。这样,当您尝试访问模型时,我们将其命名为 Order,对于此示例,您可以只说 for user in User.objects.all(): created_orders = user.creator.all(),这将返回为该 User 实例创建的所有订单。
  • related_name 应该是复数
【解决方案2】:

我认为您正在寻找的是 ForeignKeyFields 上的 related_name 属性。这将允许您引用同一个表,但为关系赋予 django 特殊名称。

更多信息:

【讨论】:

    【解决方案3】:

    从错误消息中,听起来您正试图将两个外键放在通过through 参数到ManyToManyField 使用的中间表上的同一个对象,documentation for which states

    当您设置中介时 模型,您明确指定外部 所涉及模型的关键 在多对多关系中。这 显式声明定义了如何 两个模型是相关的。

    有一些限制 中间模型:

    • 您的中间模型必须包含一个 - 并且只有一个 - 外键 目标模型(这将是 Person 在我们的示例中)。如果你有超过 一个外键,一个验证错误 将被提升。
    • 您的中间模型必须包含一个 - 并且只有一个 - 外键 源模型(这将是 Group 在我们的示例中)。如果你有超过 一个外键,一个验证错误 将被提升。

    【讨论】:

      【解决方案4】:

      使用related_name 是我的解决方案:

      class Sample(models.model):
          ...
      
      class Mymodel(models.model):
          example1 = models.ForeignKey(Sample, related_name='sample1')
          example2 = models.ForeignKey(Sample, related_name='sample2')
      

      【讨论】:

        【解决方案5】:

        两列是一个表的一部分这一事实意味着这两个字段是相关的,因此单独引用它们并不理想。您的模型的 ForeignKey 应该是您引用的表的主键:

        event = models.ForeignKey('event')
        

        然后您可以这样引用列:

        foo.event.actor
        foo.event.receiver
        

        如果您希望您也可以更改您的类/模型引用具有属性的外部属性的方式。在您的课堂上,您将执行以下操作:

        @property
        def actor(self):
          return self.event.actor
        @property
        def receiver(self):
          return self.event.receiver
        

        这将允许您随后调用 foo.actor 和 foo.receiver,但我相信更长的 foo.event.actor 会更 Pythonic

        【讨论】:

          猜你喜欢
          • 2011-04-13
          • 1970-01-01
          • 1970-01-01
          • 2021-04-01
          • 2020-12-23
          • 2020-05-07
          • 2015-10-17
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多