0

我有以下 Django 模型:

class User(models.Model):
    username = models.CharField(max_length=50, unique=True)
    name = models.CharField(max_length=100)

class Url(models.Model):
    user = models.ManyToManyField(User)
    url = models.URLField()

class Keywords(models.Model):
    url = models.ManyToManyField(Url)
    keyword = models.CharField(max_length=100)

现在,我想要数据库中任意两个用户的所有常用关键字:

username1 = 'user1'
username2 = 'user2'

尝试1:

Keyword.objects.filter(url__user__username=username1).filter(url__user__username=username2).values('keyword', 'url__url').distinct()

// Returns empty list []   [ Wrong ]

尝试2:

k1 = [ k.keyword for k in Keyword.objects.filter(url__user__username=username1) ]
k2 = [ k.keyword for k in Keyword.objects.filter(url__user__username=username2) ]

common_k = list(set(k1).intersection(set(k2)))
print common_k

// Return list of common keys (As Expected) [ Correct ]

我在尝试 1 中做错了什么?

请注意:乍一看.filter(url__user__username=username1).filter(url__user__username=username2)似乎是错误的,但它有一个多对多的关系,它应该可以工作。

尝试 1 的测试输入

newuser1 = User.objects.get(username='newuser1')
newuser2 = User.objects.get(username='newuser2')

url = Url(url='http://common.com/')
url.save()
url.user.add(newuser1)
url.user.add(newuser2)

key = Keyword(keyword='common')
key.save()
key.url.add(url)

现在,我对此进行了尝试 1 和尝试 2,并得到了预期的正确结果。我得到andcommon的关键字。newuser1newuser2

现在,尝试 2 肯定是正确的,那么我在尝试 1 中做错了什么?

4

3 回答 3

2

Attempt1将 url 过滤到用户名为 username1 的用户,然后将该查询的结果过滤到用户名为 username2 的用户。但是第一个列表只能包含 username1 的列表,因此第二个过滤器的结果将始终为空。

但是,您会在Attempt2中找到这两个查询之间的交集,而不是按顺序应用它们。这是完全不同的,并且会给出正确的答案。

您可以将此方法添加到您的用户类中,以便您可以这样做user1.commonKeywordsWithUser(user2),即

class User(models.Model):
    username = models.CharField(max_length=50, unique=True)
    name = models.CharField(max_length=100)

    def commonKeywordsWithUser(user):
        k1 = [ k.keyword for k in Keyword.objects.filter(url__user__username=self.name) ]
        k2 = [ k.keyword for k in Keyword.objects.filter(url__user__username=user.name) ]

        return list(set(k1).intersection(set(k2)))
于 2012-08-06T10:39:37.800 回答
0
set_1 = set(Keyword.objects.filter(url__user__username=username1).values_list('keyword'))
set_2 = set(Keyword.objects.filter(url__user__username=username2).values_list('keyword'))
common_keywords = list(set_1 & set_2)

单一查询的解决方案:

from django.db.models import Q
Keyword.objects.filter(url__user__username=username1).exclude(~Q(url__user__username=username2)).values('keyword', 'url__url').distinct()

使用单个查询的解决方案(来自 2 个用户的不同 url 产生相同的关键字未删除):

from django.db.models import Q
Keyword.objects.filter(url__user__username=username1).exclude(~Q(url__user__username=username2)).values('keyword', 'url__url').distinct('keyword', 'url__url')
于 2012-08-06T11:07:36.627 回答
0

您可以尝试以下方法(对于尝试 1):

Keyword.objects.filter(url__user__username=username1, keyword__in=Keyword.objects.filter(url__user__username=username2).values_list('keyword', flat=True)).values_list('keyword', flat=True).distinct()
于 2012-08-07T05:25:31.150 回答