【问题标题】:Django Models ManyToMany and Foreign KeyDjango 建模多对多和外键
【发布时间】:2012-07-10 15:07:42
【问题描述】:

试图更好地处理 django 数据库关系的处理方式。 任何想法表示赞赏。

考虑以下示例模型:

class Things(models.Model):
    name = models.CharField(max_length=20)

class Stuff(models.Model):
    name = models.CharField(max_length=20)
    information = models.ManyToManyField('Information')
    things = models.ForeignKey('Things')

class Information(models.Model):
    name = models.CharField(max_length=20)
    stuff = models.ForeignKey('Stuff')

syncdb: AttributeError: 'ManyToManyField' object has no attribute 'ForeignKey' 导致错误。如果我在Stuff 模型中同时包含ManyToManyFieldForeign Key 字段,则会导致错误结果。

有没有办法让这两种关系都存在?感谢您的任何想法。

【问题讨论】:

  • 是不是有冲突。在 Stuff 中,您有 ManyToManyInformation,但在 ManyToOne 中有 Stuff 在 信息.
  • 从您的代码示例中无法判断 Information 和 Stuff 之间的关系应该是一对多还是多对多。
  • 这个想法是Stuff 可以有多个information,但Information 引用了一种Stuff。所以从StuffInformation 的ManyToMany,以及从InformationStuff 的ForeignKey。它在我的脑海中效果很好,但在 Django 中却不行。有什么想法吗?

标签: python database django models relationships


【解决方案1】:

如果你想知道每个stuff 链接了多少information,django 会提供一个默认的manager,让你可以倒退;为此,您不需要 stuff 中的外键。

class Things(models.Model):
    name = models.CharField(max_length=20)

class Stuff(models.Model):
    name = models.CharField(max_length=20)
    information = models.ManyToManyField('Information')
    things = models.ForeignKey('Things')

class Information(models.Model):
    name = models.CharField(max_length=20)

此模型将允许您执行以下查询:

  • information 对应的 stuff X 是什么?”
  • “对于stuffYinformation 关联的是什么?”
  • “为thingZ找到所有stuffinformation

此外,它还允许您为每个stuff 拥有多个information,为每个thing 拥有多个stuff

一开始就写下这些问题将帮助您开发准确的模型,而无需在数据库中添加不必要的链接/关系。

【讨论】:

    【解决方案2】:

    基本上你会得到这样的错误:

    $python manage.py syncdb
    Error: One or more models did not validate:
    t.stuff: Reverse query name for m2m field 'information' clashes with field  'Information.stuff'. Add a related_name argument to the definition for 'information'.
    t.information: Reverse query name for field 'stuff' clashes with m2m field 'Stuff.information'. Add a related_name argument to the definition for 'stuff'.
    

    为什么?很简单,你有两个相互引用的表,这里的问题是,当应用反向查找时,django 会生成相同的名称,从而产生冲突。

    要解决这个问题,就像错误状态一样,您需要添加related_name 这样django 就知道如何区分不同的反向调用。

    from django.db import models
    
    class Things(models.Model):
        name = models.CharField(max_length=20)
    
    class Stuff(models.Model):
        name = models.CharField(max_length=20)
        information = models.ManyToManyField('Information', related_name = 'information_information')
        things = models.ForeignKey('Things')
    
    class Information(models.Model):
        name = models.CharField(max_length=20)
        stuff = models.ForeignKey('Stuff', related_name = 'information_stuff')
    

    对不起,我的名字不是很有创意,这应该可以。

    【讨论】:

    • 感谢您的意见。然而,向模型添加“related_name”参数并没有解决问题。 Python 仍然说:'ManyToManyField' object has no attribute 'ForeignKey',只有当我在 Stuff 模型上有 both 外键和 ManyToManyField 时。
    • @NickB 你一定在做别的事情,因为我发布的例子工作得很好,你必须测试你自己的代码,这可能有另一个问题。
    【解决方案3】:

    我的 django 版本提供了更多信息:

    Error: One or more models did not validate:
    foo.stuff: Reverse query name for m2m field 'information' clashes with field 'Information.stuff'. Add a related_name argument to the definition for 'information'.
    foo.information: Reverse query name for field 'stuff' clashes with m2m field 'Stuff.information'. Add a related_name argument to the definition for 'stuff'.
    

    这可能足以让您继续前进。为 ManyToManyField 关系和从 Information 到 Stuff 的 ForeignKey 关系定义一个 related_name...

    information = models.ManyToManyField('Information', related_name='stuff_many_set')
    stuff = models.ForeignKey('Stuff', related_name = 'info_set')
    

    那么syncdb 会很高兴。当然,你应该确定你需要这两种关系。在这里使用通用实体名称,看起来可能有些混乱。

    【讨论】:

    • 感谢您的意见。然而,向模型添加“related_name”参数并没有解决问题。 Python 仍然说:“ManyToManyField”对象没有属性“ForeignKey”,前提是我在 Stuff 模型上同时具有外键和 ManyToManyField。
    • 您使用什么作为related_names 参数?您可能会与 django 生成的值之一发生冲突。另外:您使用的是什么版本的 django?
    猜你喜欢
    • 2012-07-22
    • 2021-08-28
    • 2015-01-29
    • 1970-01-01
    • 1970-01-01
    • 2020-03-26
    • 1970-01-01
    • 1970-01-01
    • 2016-02-05
    相关资源
    最近更新 更多