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

我想创建一个多对多的关系从一个用户类对象和到一个用户类对象。

我有这样的东西:

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

问题是我是否可以使用类引用本身。或者我必须在 ManyToManyField中使用 "self"而不是 "MyUser"?或者还有其他(更好的)方法来做到这一点?

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

从技术上讲,我相当肯定“ MyUser”或“ self”将工作,只要它是一个字符串在任何情况下。你只是不能通过 MyUser,真正的课程。

然而,医生们总是用“自我”这个词。使用“ self”不仅更明确地说明了实际发生的情况,而且不受类名更改的影响。例如,如果您稍后将 MyUser更改为 SomethingElse,那么您还需要更新任何对“ MyUser”的引用。问题是,由于它是一个字符串,IDE 不会提醒您错误,因此错过它的可能性更大。使用“ self”将会起作用,不管这个类的名字是现在还是将来。

不要在 ManyToManyField 中使用“ self”,使用 django 表单提交时会导致对象相互链接

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


...
aTagForm.save()

结果:

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

如果使用 自我我的用户,在这两种情况下都会得到 NameError。你应该把 “自我”写成字符串。请看下面的例子:

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

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

详情查询: https://docs.djangoproject.com/en/3.0/ref/models/fields/#django.db.models.ManyToManyField

我认为应该是班名而不是自我。因为这样使用自我

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

当我加上“父母”时:

user1.parent.add(user2)

我在数据库中有两条这样的记录: enter image description here

使用类名时,比如:

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

我在数据库里有一条这样的记录: enter image description here

注意,我对 pk 使用 uuid,而对 django 使用3.1

编辑: 如@shinra-tensei 在 这个答案中解释的注释,如果我们使用 self,我们必须将 symmetrical设置为 False。Django 文档: ManyToManyFieldd.右对称

不要忘记使用对称 = 假,如果你使用。或。方法,并且不希望对象在关系的另一端更新自己在关系字段中的数据。

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