16

Django でまばらな設定テーブルを作成しています。私のモデルは単純です:

class Preference(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='preferences')
    preference = models.CharField(max_length=255, db_index=True)
    value = models.BooleanField()

一部のプリファレンスにはデフォルトの状態があるため、データベースに次の 2 つの質問をする必要があります。「このプリファレンスを特定の値に設定しているユーザーは誰ですか?」および「この設定をその値に設定していないユーザーは?

私の問題は、前者の質問は機能しますが、後者の質問 (同じクエリ句ですが、 a のexclude()代わりに a を使用filter()) は機能しないことです。例えば:

私のテスト データベースには 14 人のユーザーがいて、1 人のユーザーに 2 つのプリファレンス セットが'PREF_A'ありTrueます。'PREF_B'False

>>> User.objects.all().count()
14
>>> User.objects.filter(preferences__preference="PREF_A", preferences__value=True).count()
1
>>> User.objects.exclude(preferences__preference="PREF_A", preferences__value=True).count()
13
>>> User.objects.filter(preferences__preference="PREF_A", preferences__value=False).count()
0
>>> User.objects.exclude(preferences__preference="PREF_A", preferences__value=False).count()
13

したがって、私の結果は次のように述べています。

全部で 14 人のユーザーがいます

  • 1 人のユーザーが PREF_A を True に設定しています

  • 13 人のユーザーが PREF_A を True に設定していません

  • 0 人のユーザーの PREF_A が False に設定されています

  • 13 人のユーザーが PREF_A を False に設定していません <--- これは不正確です

このクエリのどこが間違っているのでしょうか? また、特定の設定が特定の値に設定されているユーザーを適切に除外するクエリを作成するにはどうすればよいでしょうか?

動作が異なるかどうかを確認するためにと を使用してみQましたが、結果は同じでした。~Q

4

3 に答える 3

29

これは Django にまだ存在する落とし穴であり、exclude()は の逆として機能しませんfilter()違いを説明するドキュメントは次のとおりです。

ノート

filter()上記のように、複数値のリレーションシップにまたがる for クエリ の動作は、 for と同等に実装されていませんexclude()。代わりに、1 回のexclude()呼び出しの条件が必ずしも同じ項目を参照するとは限りません。

たとえば、次のクエリは、見出しに「レノン」を含むエントリと 2008 年に発行されたエントリの両方を含むブログを除外します。

Blog.objects.exclude(
    entry__headline__contains='Lennon',
    entry__pub_date__year=2008,
)

ただし、 を使用した場合の動作とは異なり、filter()両方の条件を満たすエントリに基づいてブログを制限することはありません。これを行うには、つまり、2008 年に公開された「レノン」で公開されたエントリを含まないすべてのブログを選択するには、次の 2 つのクエリを作成する必要があります。

Blog.objects.exclude(
    entry__in=Entry.objects.filter(
        headline__contains='Lennon',
        pub_date__year=2008,
    ),
)

あなたがやってきたことは、おそらく進むべき道です。

于 2013-05-23T09:28:58.230 に答える