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

问题描述 投票:0回答:6

我想创建一个与用户类对象之间的多对多关系。

我有这样的东西:

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

问题是我是否可以使用自身内部的类引用。还是我必须在

"self"
中使用
"MyUser"
而不是
ManyToManyField
?或者有另一种(更好的)方法吗?

python django django-models many-to-many
6个回答
106
投票

从技术上讲,我很确定“MyUser”或“self”会起作用,只要它在任何一种情况下都是字符串。你只是不能通过

MyUser
,真正的课程。

但是,文档总是使用“self”。使用“self”不仅可以更明确地说明实际发生的事情,而且它不受类名更改的影响。例如,如果您稍后将

MyUser
更改为
SomethingElse
,则您还需要更新对“MyUser”的任何引用。问题是因为它是一个字符串,您的 IDE 不会提醒您错误,因此您错过它的可能性更大。无论现在或将来班级的名字是什么,使用“self”都可以。


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

19
投票

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

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

ref:Django 文档:ManyToManyField.symmetrical


6
投票

我觉得应该是类名而不是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 文档:ManyToManyField.symmetrical


3
投票

如果你使用 selfMyUser,在这两种情况下你都会得到一个 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


0
投票

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

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

 ...
 aTagForm.save()

结果:

 a.subTag == b
 b.subTag == a
© www.soinside.com 2019 - 2024. All rights reserved.