在Django中,symmetrical=True是什么意思?

25
例如:
class Contact(models.Model):
    contacts = models.ManyToManyField('self', through='ContactRelationship', symmetrical=False)

symmetrical=False参数是什么意思?

应该在什么情况下将其保留为True,在什么情况下应将其设置为False

这个设置会如何影响数据库(是否会创建额外的列等)?


7
symmetrical=True 会导致在两个对象之间创建两行,因为其是双向的。例如:如果 AB 的朋友,那么 B 就是 A 的朋友,因此我们需要在好友表中创建两行,第一行表示关系 A -> B,第二行表示 B -> A - Ozgur Vatansever
3个回答

37

假设你有两个联系人实例,John和Judy。你可能决定将John作为Judy的联系人。这个动作是否也应该将Judy作为John的联系人?如果是,symmetrical=True。如果不是,则symmetrical=False


啊,好的,我现在明白了。但是,为什么要有两行,第一列和第二列翻转呢?如果Judy.contacts包含一个指向John的对象,难道不可以简单地做类似于John.contacts_set的事情来获取源自Judy的同样的对象吗?或者,再次通过表格并将第1列视为第2列,将第2列视为第1列以达到对称的效果? - davidtgq
1
我相信,如果您使用中介模型即through=,您必须将symmetrical=False设置为真。无论如何,我不确定但我怀疑当symmetrical=True时会重复行。请记住,ORM将您的代码与数据库分离;因此,该标志更可能影响DB查询的结构而不是DB本身的结构。但我不是专家,也许其他人会对此发表意见! - danyamachine

17
以下是文档中的说明:

仅在自身的ManyToManyFields定义中使用。考虑以下模型:

from django.db import models
class Person(models.Model):
    friends = models.ManyToManyField("self")

当Django处理这个模型时,它会识别到自己有一个ManyToManyField,并因此不会向Person类添加person_set属性。相反,ManyToManyField被认为是对称的——也就是说,如果我是你的朋友,那么你也是我的朋友。
默认情况下,Many to Many Field的symmetrical值为True,这是双向关系。
使用中间表(symmetrical=False):
但是,您也可以想象一种不需要这种类型关系的情况,因此可以添加symmetrical=False。而且,通过使用中间表可以实现这一点,因为如果使用中间表,则默认情况下symmetrical为False。
使用中间模型定义递归关系始终被定义为非对称的——也就是说,symmetrical=False——因此存在“源”和“目标”的概念。在这种情况下,field1将被视为关系的“源”,而field2将被视为“目标”。
因此,您可以想象一种需要方向的情况,例如,有一个Node模型,并且它使用中间表与自身建立关系。如果我们没有方向要求,我们可以使用前面显示的示例。但现在我们还需要从一个节点到另一个节点的方向,其中一个是源,另一个是目标,由于这种关系的性质,它不能是对称的。

谢谢。确认一下我的理解是否正确:如果ManyToManyField是对称的,那么它是否只是将本来在Person.person_set中的所有内容都放到了Person.friends中?如果我理解正确,这是Django的一个特性,而不是数据库的特性——我们可以在对称True或False之间来回切换,而不需要进行任何数据库迁移的更改? - davidtgq
1
这完全是 Django 的事情,但迁移仍将发生,尽管它不会影响数据库。它的行为更像是“blank”关键字,如果您将其添加到字段中,将导致迁移,但它与数据库没有直接关系,而仅在 Django 表单中使用。 - AKS
父节点和子节点始终被定义为非对称的。 - WeizhongTu
1
工作链接:https://docs.djangoproject.com/en/stable/ref/models/fields/#django.db.models.ManyToManyField.symmetrical - thrillhouse
@thrillhouse 谢谢。我已经在答案中更新了链接。 - AKS

3

对称关系

class User(models.Model)
...
    friends = models.ManyToManyField("self")
...
alice = User()
bob = User()
bob.friends.add(alice)

现在,Bob是Alice的朋友,而Alice也是Bob的朋友。

非对称关系

class User(models.Model)

     ...
     parents = models.ManyToManyField("self", symmetrical=False)
 ...
 alice = User()
 bob = User()
 bob.parent.add(alice)

现在,Alice是Bob的父母,但Bob不是Alice的父母。

原始答案:https://stackoverflow.com/a/34998422/5993109


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接