Django多对多(m2m)与同一模型的关系

时间:2012-07-30 12:03:25

标签: python django django-models many-to-many

我想从用户类对象创建多对多关系。

我有这样的事情:

class MyUser(models.Model):
    ...
    blocked_users = models.ManyToManyField(MyUser, blank=True, null=True)

问题是我是否可以在自身内部使用类引用。或者我必须在"self"中使用"MyUser" ManyToManyField {{1}}个?或者还有另一种(更好的)方法吗?

6 个答案:

答案 0 :(得分:60)

从技术上讲,我很确定“MyUser”或“self”会起作用,只要它在任何一种情况下都是一个字符串。你无法通过MyUser,实际的班级。

但是,文档总是使用“自我”。使用“self”不仅更明确地了解实际发生的事情,而且它不受类名更改的影响。例如,如果您稍后将MyUser更改为SomethingElse,则您还需要更新对“MyUser”的任何引用。问题是因为它是一个字符串,你的IDE不会提醒你错误,所以你错过了它的可能性更大。无论现在或未来的班级名称如何,使用“自我”都会有效。

答案 1 :(得分:37)

class MyUser(models.Model):
    ...
    blocked_users = models.ManyToManyField("self", blank=True)

答案 2 :(得分:3)

如果您对相关对象使用 .clear() 或 .add() 方法并且不想在关系另一侧的对象更新关系字段中的自己的数据,请不要忘记使用对称=假。

some_field = models.ManyToManyField('self', symmetrical=False)

答案 3 :(得分:1)

如果您使用 self MyUser ,则在两种情况下都会出现NameError。您应该将“ self” 写为字符串。请参见下面的示例:

class MyUser(models.Model):
    ...
    blocked_users = models.ManyToManyField("self", blank=True, null=True)

如果关系不是对称的,请不要忘记将对称属性设置为 False

有关更多详细信息,请检查:https://docs.djangoproject.com/en/3.0/ref/models/fields/#django.db.models.ManyToManyField

答案 4 :(得分:1)

我认为它应该是类名而不是self。因为像这样使用自我

parent = models.ManyToManyField('self', null=True, blank=True)

当我添加父母时:

user1.parent.add(user2)

我在数据库中有2条记录,如下所示: enter image description here

并使用类似这样的类名:

parent = models.ManyToManyField('User', null=True, blank=True)

我在数据库中有一条记录,如下所示: enter image description here

请注意,我将uuid用于pk,而我使用django 3.1

编辑: 正如@ shinra-tensei在this answer中解释为注释一样,如果我们使用self,则必须将symmetrical设置为False。记录在Django Documents: ManyToManyField.symmetrical

答案 5 :(得分:0)

在ManyToManyField中不要使用“ self”,当使用django表单提交它时,它将导致对象彼此链接

class Tag(models.Model):
    ...
    subTag = models.ManyToManyField("self", blank=True)

 ...
 aTagForm.save()

和结果:

 a.subTag == b
 b.subTag == a