首页 > 解决方案 > django相关模型字段查询(共同好友)

问题描述

我有一个友谊模型:


class Friendship(models.Model):
    user = models.ForeignKey(
        Account, on_delete=models.CASCADE, related_name="friend1", null=True, blank=True)
    other_user = models.ForeignKey(
        Account, on_delete=models.CASCADE, related_name="friend2", null=True, blank=True)
    date_created = models.DateTimeField(auto_now=True)

    objects = FriendshipManager()

    class Meta:
        verbose_name = "friendship"
        verbose_name_plural = "friendships"
        unique_together = ("user", "other_user")

    def __str__(self):
        return f'{self.user} is friends with {self.other_user}.'

这个函数返回两个帐户的共同朋友的所有用户


def mutual_friends(self, account1, account2):
        mutual_friends = Account.objects.filter(
            Q(friend2__user=account1) & Q(friend2__user=account2))
        return mutual_friends

根据我对查询 api 如何工作的(有限)理解,我认为这应该返回与 Friendship 表有“friend2”关系的所有用户,其中“friend1”用户是 account1 或 account2。我仍然习惯于使用 django 进行查询,所以如果有人能让我知道我做错了什么,那就太好了。

谢谢!

标签: pythonsqldjangodjango-rest-framework

解决方案


你的模型设计对我来说似乎不合适。到目前为止,您可以将任何Account实例作为useror other_user,并且由于它们都引用相同的模型 ( Account),因此在从数据库中进行任何检索时,您需要考虑这两个字段。

更好的设计 IMO 是ManyToManyField在模型中对自身使用(多对多关系)Account,因为一个帐户可以有多个其他帐户作为朋友,反之亦然。所以:

class Account(models.Model):
    ...
    friends = models.ManyToManyField('self')
    ...

现在,您可以添加朋友,例如:

account_foo.friends.add(account_bar, account_spam)

account_*Account实例。

你可以得到所有account_foo喜欢的朋友:

account_foo.friends.all()

查看多对多文档,了解数据集成和查询的各种示例。


现在,要找到 egaccount_foo和的共同朋友account_bar,您可以先获取 的所有朋友,account_foo然后查看其中哪些也是 的朋友account_bar

friends_with_foo = account_foo.friends.values_list('pk', flat=True)
mutual_friends_of_foo_bar = account_bar.friends.filter(pk__in=friends_with_foo)

推荐阅读