我有类似以下的东西:
class MyUser(models.Model):
...
blocked_users = models.ManyToManyField(MyUser, blank=True, null=True)
我的问题是我是否可以在类本身内部使用类引用。或者在ManyToManyField
中必须使用"self"
而不是"MyUser"
?或者是否有另一种(更好的)方法来实现这个?
class MyUser(models.Model):
...
blocked_users = models.ManyToManyField(MyUser, blank=True, null=True)
我的问题是我是否可以在类本身内部使用类引用。或者在ManyToManyField
中必须使用"self"
而不是"MyUser"
?或者是否有另一种(更好的)方法来实现这个?
从技术上讲,“MyUser”或“self”都可以使用,只要在两种情况下它是一个字符串。但是,文档总是使用“self”。使用“self”不仅更明确地说明实际发生的情况,而且不受类名更改的影响。例如,如果您稍后将“MyUser”更改为“SomethingElse”,则还需要更新对“MyUser”的任何引用。问题在于,由于它是一个字符串,因此您的IDE不会警告您出现错误,因此很容易错过。使用“self”无论现在或未来类的名称是什么都可以工作。
class MyUser(models.Model):
...
blocked_users = models.ManyToManyField("self", blank=True)
null=True
对 ManyToManyFields 没有影响。 - asgaines如果您使用.clear()或.add()方法来处理相关对象,并且不希望关系另一侧的对象更新其关系字段中的数据,请不要忘记使用symmetrical=False。
some_field = models.ManyToManyField('self', symmetrical=False)
parent = models.ManyToManyField('self', null=True, blank=True)
当我添加父级元素时:
user1.parent.add(user2)
我在数据库中有两条记录,如下所示:
可以使用类名来进行操作,例如:
parent = models.ManyToManyField('User', null=True, blank=True)
我在数据库中有一条记录,如下所示:
请注意,我使用 uuid 作为主键,并且我使用的是 Django 3.1。
编辑:
如 @shinra-tensei 在此答案中的评论中所解释的那样,如果我们使用 self,则必须将 symmetrical
设置为 False。有关详细信息,请参见Django 文档:ManyToManyField.symmetrical。
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
在ManyToManyField中不要使用'self',否则会导致对象相互链接,当使用Django表单提交时
class Tag(models.Model):
...
subTag = models.ManyToManyField("self", blank=True)
...
aTagForm.save()
结果为:
a.subTag == b
b.subTag == a
symmetrical = False
,它存在的目的是允许您使用 'self'
代替模型名称。具体请参考:https://docs.djangoproject.com/en/2.2/ref/models/fields/#django.db.models.ManyToManyField.symmetrical - Shinra tensei