编辑:
防止大家阅读过多:问题是我不明白什么
Q(tag_rep__tag=tag.id)
确实适用于这个模型:
class Item(models.Model):
tag_rep=generic.GenericRelation(TaggedItem)
很可能 tag_rep__tag 确实返回标签列表,而不是单个标签。所以我不能像我那样做查询。我如何比较 tag_rep__tag 以确定它是否
- 包含任何标签列表
- 包含所有标签列表
我正在尝试为具有标记标签的项目构建一个基于查询集的标签过滤器。我已经成功创建了过滤器,但它们基于 pythonfilter
并返回一个列表:
class TagFilter(object):
def __init__(self,any_tags,avoid_tags,all_tags):
# all tags as tag instances
self.any_tags = any_tags
self.avoid_tags = avoid_tags
self.all_tags = all_tags
def seek_any_tags(self, item):
for tag in self.any_tags:
if tag in item.tags:
return True
return False
def items_with_any_tags(self,items):
return filter(self.seek_any_tags,items)
这工作得很好,但现在我需要一个查询集作为回报来传递给一个表单集。所以当前方法不再起作用,因为它返回一个列表。为了能够访问我的模型的标签,我这样做了:
from django.contrib.contenttypes import generic
from tagging.models import TaggedItem
class Item(models.Model):
# some_fields here
tag_rep = generic.GenericRelation(TaggedItem)
过滤器seek_any_tags
是我唯一可以以数据库查询的形式重建的过滤器。在阅读了一些 SO 帖子并进行了大量谷歌搜索后,我想出了这个解决方案:
def seek_any_tags_qs(self,items):
if self.any_tags!=None:
q = reduce(lambda x, y: x | y, [Q(tag_rep__tag=tag.id) for tag in self.any_tags])
items = items.filter(q)
return items
非常好,是的,我对此感到有点自豪。但是现在我要构建另外两个过滤器:avoid_any_tags
和seek_all_tags
. 我尝试以与seek_any_tags
过滤器相同的方式进行操作:
def avoid_any_tags_qs(self,items):
if self.avoid_tags != None:
q = reduce(lambda x, y: x | y, [Q(tag_rep__tag=tag.id) for tag in self.avoid_tags])
items = items.exclude(q)
return items
def seek_all_tags_qs(self,items):
if self.all_tags != None:
q = reduce(lambda x, y: x & y, [Q(_tags__contains=tag.name) for tag in self.seek_tags])
items.filter(q)
return items
avoid_any_tags
应该排除在避免标签中具有任何标签的每个项目。最后一个,seek_all_tags
应该只返回在 all_tags 中包含所有标签的项目。
但avoid_any_tags
不能像执行的那样工作。它只排除在 Avoid_tags 中有标签的元素,没有其他标签。如果一个项目有任何不在 Avoid_tags 中的标签,它不会被排除。为什么不?