您好我正在尝试为 Django 编写一个标记系统,但今天我在过滤器或 Q 对象 (django.db.models.Q) 中遇到了一个奇怪的行为。
我写了一个函数,将搜索字符串转换为 Q 对象。下一步是使用这些查询过滤 TaggedObject。但不幸的是,我得到了一个奇怪的行为。
仅搜索一个 Tag 元素:
当我搜索(id=20)
=>
时Q: (AND: ('tags__tag__id', 20))
,它返回 2 个 ID 为 1127 和 132 的标记对象
当我搜索(id=4)
=>
时Q: (AND: ('tags__tag__id', 4))
,它也返回 2 个对象,但这次是 1180 和 1127
这是请求的 SQL 查询:
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
使用“或”连词搜索两个标签:
直到这里一切都很好,但是当我进行更复杂的查询时,例如(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 的对象被返回了两次,但这不是我想要的行为。我是否必须忍受它,并统一该列表,或者我可以做一些不同的事情。Q 对象的表示对我来说看起来不错。
搜索两个标签“和”连词
但最糟糕的是现在,当我搜索(id=20) and (id=4)
=>
时Q: (AND: ('tags__tag__id', 20), ('tags__tag__id', 4))
,它根本不返回任何对象。但为什么?表示应该没问题,并且 id 为 1127 的对象被两者标记。我错过了什么?
这里又是 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 语句是错误的。至少不是我想要的,因为这里它想要一个 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):
...
谢谢你的帮助