我有以下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,并按预期得到了正确的结果。我将common
作为newuser1
和newuser2
的关键字。
现在,尝试2肯定是正确的,那么我在尝试1时做错了什么?
答案 0 :(得分:2)
Attempt1 正在将网址过滤到名称为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)))
答案 1 :(得分: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个用户的不同网址导致相同的关键字未被删除):
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')
答案 2 :(得分: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()