こんにちは私はDjangoのタグ付けシステムを作成しようとしていますが、今日、フィルターまたはQオブジェクト(django.db.models.Q)で奇妙な動作が発生しました。
検索文字列をQオブジェクトに変換する関数を作成しました。次のステップは、これらのクエリでTaggedObjectをフィルタリングすることです。しかし、残念ながら私は奇妙な振る舞いをします。
1つのタグ要素のみを検索します。
検索(id=20)
=>
Q: (AND: ('tags__tag__id', 20))
すると、IDが1127と132の2つのタグ付きオブジェクトが返されます。
(id=4)
=>
を検索するQ: (AND: ('tags__tag__id', 4))
と、2つのオブジェクトも返されますが、今回は1180と1127です。
これが、relutingSQLクエリです。
SELECT "django_content_type"."id", "django_content_type"."name", "django_content_type"."app_label", "django_content_type"."model"
FROM "django_content_type"
WHERE ("django_content_type"."model" = slogan AND "django_content_type"."app_label" = slogans )
ORDER BY "django_content_type"."name" ASC
SELECT "slogans_slogan"."id", "slogans_slogan"."headline", "slogans_slogan"."text", "slogans_slogan"."author"
FROM "slogans_slogan"
INNER JOIN "htags_objecttagbridge" ON ("slogans_slogan"."id" = "htags_objecttagbridge"."object_id")
WHERE ("htags_objecttagbridge"."tag_id" = 4 AND "htags_objecttagbridge"."content_type_id" = 9 )
LIMIT 21
'または'接続詞で2つのタグを検索します。
(id=4) or (id=20)
ここまではすべて問題ありませんが、 =>
のようにもう少し複雑なクエリを実行すると、Q: (OR: ('tags__tag__id', 4), ('tags__tag__id', 20))
4(!)オブジェクト1180、1127、1127、132が返されます。
およびSQL:
SELECT "slogans_slogan"."id", "slogans_slogan"."headline", "slogans_slogan"."text", "slogans_slogan"."author"
FROM "slogans_slogan"
INNER JOIN "htags_objecttagbridge" ON ("slogans_slogan"."id" = "htags_objecttagbridge"."object_id")
WHERE ((("htags_objecttagbridge"."tag_id" = 4 AND "htags_objecttagbridge"."content_type_id" = 9 ) OR "htags_objecttagbridge"."tag_id" = 20 ) AND "htags_objecttagbridge"."content_type_id" = 9 )
LIMIT 21
しかし、ID 1127のオブジェクトは2回返されますが、それは私が望む動作ではありません。私はそれと一緒に暮らす必要があり、そのリストを統一する必要がありますか、それとも私は別のことをすることができますか?Qオブジェクトの表現は私にはうまく見えます。
2つのタグ'と'接続詞を検索します
しかし、最悪の場合、(id=20) and (id=4)
=>
を検索するとQ: (AND: ('tags__tag__id', 20), ('tags__tag__id', 4))
、オブジェクトがまったく返されません。しかし、なぜ?表現は問題なく、ID1127のオブジェクトは両方でタグ付けされている必要があります。私は何が欠けていますか?
これがSQLです。
SELECT "slogans_slogan"."id", "slogans_slogan"."headline", "slogans_slogan"."text", "slogans_slogan"."author"
FROM "slogans_slogan"
INNER JOIN "htags_objecttagbridge" ON ("slogans_slogan"."id" = "htags_objecttagbridge"."object_id")
WHERE ("htags_objecttagbridge"."tag_id" = 4 AND "htags_objecttagbridge"."content_type_id" = 9 AND "htags_objecttagbridge"."tag_id" = 20 )
LIMIT 21
[編集]: このSQLステートメントが間違っていることに気づきました。少なくとも私が望むものではありません。ここでは、1つのObjectTagBridgeのIDが4であり、同時にIDが20であるためです。しかし、私の場合、これらは2つの異なるものです。
関係するクラスの関連部分もここにあります:
class TaggedObject(models.Model):
"""
class that represent a tagged object
"""
tags = generic.GenericRelation('ObjectTagBridge',
blank=True, null=True)
class ObjectTagBridge(models.Model):
"""
Help to connect a generic object to a Tag.
"""
# pylint: disable-msg=W0232,R0903
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey('content_type', 'object_id')
tag = models.ForeignKey('Tag')
class Tag(models.Model):
...
ご協力いただきありがとうございます