HWM*_*ker 1 django search filter django-q
您好我正在尝试为Django编写标记系统,但今天我在过滤器或Q对象(django.db.models.Q)中遇到了一个奇怪的行为.
我写了一个函数,将搜索字符串转换为Q对象.下一步是使用这些查询过滤TaggedObject.但不幸的是,我得到了一个奇怪的行为.
当我搜索(id=20)
=>
Q: (AND: ('tags__tag__id', 20))
并返回2个ID为1127和132的Taged Objects时
当我搜索(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
Run Code Online (Sandbox Code Playgroud)
直到这里一切都很好,但当我做一个更复杂的查询,如(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
Run Code Online (Sandbox Code Playgroud)
但是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
Run Code Online (Sandbox Code Playgroud)
[编辑]: 我现在意识到,这个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):
...
Run Code Online (Sandbox Code Playgroud)
谢谢你的帮助
对于问题1(唯一性):您将要使您的查询与众不同.复制是该类型查询的预期行为,除非您将其区分开来.
对于问题2,您可能会遇到查询集如何工作的微妙但重要的部分.如果你这样做一个查询:
mymodel.objects.filter(tags__tag__id=4, tags__tag__id=5)
Run Code Online (Sandbox Code Playgroud)
您正在查询具有单个标记的模型,该标记同时具有id = 4和id = 5,这当然没有标记.但是,如果你改为这样查询:
mymodel.objects.filter(tags__tag__id=4).filter(tags__tag__id=5)
Run Code Online (Sandbox Code Playgroud)
你得到的模型有一些id = 4的标签,有些标签的id = 5.Q对象也是如此 - 它们需要分成单独的filter
或exclude
调用,而不是指单个Tag关系.这在此处记录.
归档时间: |
|
查看次数: |
638 次 |
最近记录: |