django ManyToMany 通过帮助

Posted

技术标签:

【中文标题】django ManyToMany 通过帮助【英文标题】:django ManyToMany through help 【发布时间】:2011-01-27 15:40:48 【问题描述】:

嘿,我有一个关于人际关系的问题。

我希望用户有友谊。所以一个用户可以和另一个用户成为朋友。我假设我需要通过友谊表使用 ManyToManyField。但我无法让它工作。有什么想法吗?

这是我的模型。

class User(models.Model):
    username = models.CharField(max_length=999)
    password = models.CharField(max_length=999)
    created_on = models.DateField(auto_now = False, auto_now_add = True)
    updated_on = models.DateField(auto_now = True, auto_now_add = False)
    friends = models.ManyToManyField('self')
    pendingFriends = models.ManyToManyField('self', through='PendingFriendship', symmetrical=False, related_name='friend_requested')

class PendingFriendship(models.Model):
    user = models.ForeignKey('User', related_name='user')
    requested_friend = models.ForeignKey('User', related_name='requested_friend')
    created_on = models.DateField(auto_now = False, auto_now_add = True)
    updated_on = models.DateField(auto_now = True, auto_now_add = False)

谢谢

【问题讨论】:

【参考方案1】:

documentation 中描述了多对多字段。做吧:

class User(models.Model):
    username = models.CharField(max_length=999)
    password = models.CharField(max_length=999)
    created_on = models.DateField(auto_now = False, auto_now_add = True)
    updated_on = models.DateField(auto_now = True, auto_now_add = False)
    friends = models.ManyToManyField('self')

如果您想在关系中添加额外的字段,您只需使用through。在this section 中描述了所有可能性的另一种描述。

当您将模型命名为 User 时,我假设您没有使用内置身份验证框架。但是如果你使用它,你不必自己实现认证,所以考虑一下。

更新: 你读过我链接到的部分吗?那里是这样描述的:

中间模型有一些限制:

您的中间模型必须包含一个 - 并且只有一个 - 目标模型的外键(在我们的示例中为 Person)。如果您有多个外键,则会引发验证错误。 您的中间模型必须包含一个 - 并且只有一个 - 源模型的外键(在我们的示例中为 Group)。如果您有多个外键,则会引发验证错误。 唯一的例外是通过中间模型与自身具有多对多关系的模型。在这种情况下,允许同一模型的两个外键,但它们将被视为多对多关系的两个(不同)边。 在使用中间模型定义从模型到自身的多对多关系时,您必须使用symmetrical=False(请参阅model field reference)。

【讨论】:

我已经更新了这个例子,你的修改。但是我仍然需要额外的表来保存数据。 嗯,我更新了我的模型,它通过了验证。我添加了几个用户。并在用户 A 的模型上创建了一个 PendingFriendship 对象。这增加了友谊,但是用户 b 的对象没有得到友谊的另一面(我假设因为“对称”值是错误的)。我希望这种关系是对称的。有什么想法吗? 要使关系对称,您有两个选择:1) 创建另一个ManyToManyField,将through_fields 选项设置为through_fields=('requested_friend', 'user'); 2) 创建另一个PendingFriendship 对象,颠倒哪个朋友是user,哪个朋友是requested_friend。在你的情况下,我认为选项 1) 更有意义。【参考方案2】:

This blog 解释了您的需求。从博客中,您只需在这一行中更改相关名称:

pendingFriends = models.ManyToManyField('self', through='PendingFriendship', symmetrical=False, related_name='friend_requested')

进入:

related_name='friend_requested+'

但是,我仍然无法让它自动创建对称关系。

【讨论】:

以上是关于django ManyToMany 通过帮助的主要内容,如果未能解决你的问题,请参考以下文章

通过特定的 ManyToMany 对象订购 Django QuerySet

django 模型:如何克服“通过”ManyToMany 选项限制

Django ManyToMany 通过不同步或迁移

Django ManyToMany 字段上的自定义列名

Django ManyToMany 通用“通过”模型

Django 模型 ManytoMany getter