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)

ここで、データベースから任意の 2 人のユーザーに共通するすべてのキーワードが必要です。

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とのキーワードとして取得newuser1newuser2ます。

さて、試行 2 は間違いなく正しいのですが、試行 1 で何が間違っているのでしょうか?

4

3 に答える 3

2

Attempt1は、URL を username1 という名前のユーザーの URL にフィルタリングし、そのクエリの結果を username2 という名前のユーザーの URL にフィルタリングします。ただし、最初のリストには username1 のリストしか含めることができないため、2 番目のフィルターの結果は常に空になります。

ただし、これら 2 つのクエリを順番に適用するのではなく、 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

次のようなことを試すことができます (試行 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 に答える