友谊关系的最佳模型(在 Django 中)

Posted

技术标签:

【中文标题】友谊关系的最佳模型(在 Django 中)【英文标题】:Best Models for a Friendship relation (in Django) 【发布时间】:2012-01-27 16:56:15 【问题描述】:

为社交网站建立用户之间友谊的最佳方式是什么?

可能的状态是:

没有友谊 从A到B的FriendRequest,B需要确认(这是不对称的) A 和 B 是朋友(这是对称的)

现在选择正确的模型很复杂。

我的朋友是我个人资料的一部分

很明显,A.profile.friends 与其他用户是多对多关系。

没有友谊:B 不在 A.friends 中,A 不在 B.friends 中 A 请求与 B 建立友谊:A.friends 中的 B 好友:A.friends 中的 B 和 B.friends 中的 A

但是将friend与friendrequest关系合并似乎很不干净。如果没有这种合并,数据是多余的,因为“B.friends 中的 A 而不是 A.friends 中的 B”将是未定义状态。

Friend-Lookup: A.friends.filter(friends__contains=B) #相当复杂的数据库级别查找,对程序员来说不直观

单独的表

FriendRequest很明显,一个有requester和requested_user的类,select也很明显。

Friend 模型不是很好,因为它会将 person1 和 person2 作为字段,并且所有查找都需要选择 Friends with person1=A and person2=B OR person1=B and person2=A

Friend-Lookup: Friend.objects.filter(person1=A) union Friend.objects.filter(person2=A) #unclean 需要联合两个集合

分离 many2many 表

另一种选择是带有friends 字段的Friend 模型,这是一个many2many 字段,它恰好链接到两个人。然后选择匹配朋友字段中的一个人,然后只返回模型,其中人 B 可以通过从朋友集中减去 A 来提取。但这太过分了,因为任何朋友对象都不会有超过 2 个关联的人。

Friend-Lookup: Friendship.objects.filter(persons__contains=A) #查询两个表

那么,您认为存储友谊关系最简洁、最直观的解决方案是什么?有没有常见的模式怎么做?

【问题讨论】:

这里有一个很好的例子来说明你的第三个选项github.com/revsys/django-friendship/blob/master/friendship/… 这看起来像我在 2011 年寻找的东西。我需要它的项目现在被放弃了,但也许我可以使用它。如果您想在答案中解释这些模型的一些核心方面(此处不欢迎仅链接答案),我可以接受。 【参考方案1】:

如果你不想重新实现所有这些友谊关系的东西,你可以使用以下模块:https://github.com/revsys/django-friendship

它的行为是您在第三个选项中描述的:它创建单独的 ManyToMany 表。一个用于友谊请求:

class FriendshipRequest(models.Model):
    """ Model to represent friendship requests """
    from_user = models.ForeignKey(AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='friendship_requests_sent')
    to_user = models.ForeignKey(AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='friendship_requests_received')

好友状态的另一个:

class Friend(models.Model):
    """ Model to represent Friendships """
    to_user = models.ForeignKey(AUTH_USER_MODEL, models.CASCADE, related_name='friends')
    from_user = models.ForeignKey(AUTH_USER_MODEL, models.CASCADE, related_name='_unused_friend_relation')

它还提供follow、block和相关的管理器。

【讨论】:

【参考方案2】:

我相信这是 Django 支持的扩展多对多关系的一个用例:https://docs.djangoproject.com/en/dev/topics/db/models/#intermediary-manytomany

您可以存储其他属性,而不仅仅是存储这些用户之间的连接。这应该很好地将您的问题域投影到数据库模型上。即,一旦两人中的一个人开始建立友谊,就建立您的联系,然后设置其他字段来存储谁在询问谁以及对方是否接受了友谊。

【讨论】:

是的,这就是提到的第三个选项,类似于 FriendShip.persons=models.Many2ManyField(Person),可以在同一模型中存储其他共享数据。访问是完全对称的,但它使用一张表用于友谊对象,一张表用于 m2m 字段,每个友谊对象有两个条目,效率不如 Friendship(personA, personB)。【参考方案3】:

对于一个 sql 数据库,我会为此使用多对多关系。但是如果你认为你会有很多用户,你可能需要考虑像flock-db这样专门为这类数据设计的图形数据库

http://en.wikipedia.org/wiki/Graph_database

(将常规数据保存在 sql db 中,并将关系保存在图形数据库中)

【讨论】:

有趣的选项,因为友谊是图表的一个很好的用例。但目前希望有一个有效且更重要的干净解决方案来使用 django 模型(以某种方式转换为 SQL)。

以上是关于友谊关系的最佳模型(在 Django 中)的主要内容,如果未能解决你的问题,请参考以下文章

关于自定义用户模型的 Django 最佳实践

ORM:友谊/好友关系

Django模型加入一对多关系以在模板中显示

django ManyToMany 通过帮助

在运行时在 Django 中指定关系动词?

数据库设计 - 管理这些关系的最佳方式