Django多对多(m2m)与同一模型的关系
Posted
技术标签:
【中文标题】Django多对多(m2m)与同一模型的关系【英文标题】:Django Many-to-Many (m2m) Relation to same model 【发布时间】:2012-07-28 02:25:09 【问题描述】:我想在用户类对象之间创建多对多关系。
我有这样的事情:
class MyUser(models.Model):
...
blocked_users = models.ManyToManyField(MyUser, blank=True, null=True)
问题是我是否可以在其内部使用类引用。或者我是否必须在ManyToManyField
中使用"self"
而不是"MyUser"
?或者还有其他(更好的)方法吗?
【问题讨论】:
在同一个模型上定义多对多有什么用??任何人请 @ParaM 例如,如果你有一个树状结构。主产品有子产品等。 “在同一模型上定义多对多有什么用?” 允许每个用户拥有自己的已阻止(或关注)的其他用户列表。 最佳用例是模型的树形结构。 【参考方案1】:从技术上讲,我很确定“MyUser”或“self”会起作用,只要它在任何一种情况下都是字符串。你只是不能通过MyUser
,实际的课程。
但是,文档总是使用“self”。使用“self”不仅更明确地说明实际发生的事情,而且不受类名更改的影响。例如,如果您后来将MyUser
更改为SomethingElse
,那么您还需要更新对“MyUser”的任何引用。问题是因为它是一个字符串,你的 IDE 不会提醒你错误,所以你错过它的可能性更大。无论现在或将来类的名称是什么,都可以使用“self”。
【讨论】:
在同一模型上定义多对多有什么用??任何人请 @ParaM 一个例子:您希望指定“相关文章”的文章模型 一个个人示例是一个代理,其字段指定招募他们的代理。【参考方案2】:class MyUser(models.Model):
...
blocked_users = models.ManyToManyField("self", blank=True)
【讨论】:
"self" 不起作用。使用blocked_users = models.ManyToManyField("MyUser", blank=True, null=True) 我没有说“MyUser”,我说的是“self”:docs.djangoproject.com/en/dev/ref/models/fields/…null=True
对 ManyToManyFields 没有影响【参考方案3】:
如果您对相关对象使用 .clear() 或 .add() 方法并且不想在关系的另一侧更新自己的关系字段中的数据,请不要忘记使用symmetric=False。
some_field = models.ManyToManyField('self', symmetrical=False)
【讨论】:
【参考方案4】:我认为它应该是类名而不是自我。因为像这样使用 self
parent = models.ManyToManyField('self', null=True, blank=True)
当我添加父母时:
user1.parent.add(user2)
我在数据库中有 2 条记录,如下所示:
使用类名如下:
parent = models.ManyToManyField('User', null=True, blank=True)
我在数据库中有一条这样的记录:
请注意,我使用 uuid 进行 pk,我使用 django 3.1
编辑:
正如@shinra-tensei 在this answer 中的评论所解释的那样,如果我们使用self,我们必须将symmetrical
设置为False。记录在Django Documents: ManyToManyField.symmetrical
【讨论】:
您使用的是什么数据库适配器?那里可能是一个错误...... @Ron postgres 和 mysql 都【参考方案5】:如果您使用 self 或 MyUser 在这两种情况下都会收到 NameError。您应该将 "self" 写为字符串。请看下面的例子:
class MyUser(models.Model):
...
blocked_users = models.ManyToManyField("self", blank=True, null=True)
如果关系不对称,不要忘记将 symmetrical 属性设置为 False。
更多详情请查看:https://docs.djangoproject.com/en/3.0/ref/models/fields/#django.db.models.ManyToManyField
【讨论】:
【参考方案6】:在ManyToManyField中不要使用'self',当使用django表单提交时会导致你的对象相互链接
class Tag(models.Model):
...
subTag = models.ManyToManyField("self", blank=True)
...
aTagForm.save()
结果:
a.subTag == b
b.subTag == a
【讨论】:
有什么建议吗?我从来没有遇到过问题。 我在我的演示中发现了它,最后我使用 ManyToManyField("Tag", blank=True) 来修复它 如果您不希望对象相互链接,请在创建字段 docs.djangoproject.com/en/2.2/ref/models/fields/… 时使用参数symmetrical = False
,它的存在允许您使用 'self'
名称而不是型号名称以上是关于Django多对多(m2m)与同一模型的关系的主要内容,如果未能解决你的问题,请参考以下文章
TypeError:禁止直接分配到多对多集合的前向端。请改用 meeting.set()。 Django m2m 字段出错