我有一个包含一些对象的查询集。根据某些情况或其他情况,我现在想要排除没有特定标签的所有对象(_tags是我模型上TagField的名称):
self.queryset=self.queryset.exclude(_tags__id__in=avoid)
但这只是让我错误:
Caught FieldError while rendering:
Join on field '_tags' not permitted.
Did you misspell 'id' for the lookup type?
因为我很确定我没有拼错'id',所以我做了一些关于如何使用标记这样的东西的搜索。在文档中有很多关于自定义管理器,但不知何故,我无法得到它如何使用它们来获得我想要的。
修改
将上面的代码更正为
self.queryset=self.queryset.exclude(_tags__in=avoid)
其中avoid是整数列表。这让我遇到了django-tagging的TagField只是一个特殊的CharField(或TextField?)的问题。当然,如果我只是根据整数列表查询它,那么这将不会解决任何问题。我可以尝试用这样的方式解决这个问题:
for tag in avoid:
self.queryset=self.queryset.exclude(_tags__contains=tag.name)
这不仅是丑陋的,而且还让我遇到由多个单词或其他标签的匹配部分组成的标签的问题。
我不知何故怀疑这可以通过了解django-tagging如何工作的人以更漂亮的方式解决。
答案 0 :(得分:3)
您的模型是如何定义的? _tags是ForeignKey字段吗?
如果不删除__id部分
self.queryset=self.queryset.exclude(_tags__in=avoid)
答案 1 :(得分:2)
不幸的是,不,没有更漂亮的方式。事实上,实际的解决方案甚至更加丑陋,但是当所有标签都存储在一个文本字段中时,没有别的办法:
from django.db.models import Q
startswith_tag = Q(_tags__startswith=tag.name+' ')
contains_tag = Q(_tags__contains=' '+tag.name+' ')
endswith_tag = Q(_tags__endswith=' '+tag.name)
self.queryset=self.queryset.exclude(startswith_tag | contains_tag | endswith_tag)
上面的代码假定标记用空格分隔。如果没有,您将不得不修改代码以匹配它们的分隔方式。我们的想法是,您使用分隔符作为搜索的一部分,以确保它是实际标记,而不仅仅是另一个标记的一部分。
如果您不想这样做,我建议您切换到另一个不会将它们全部转储到单个文本字段中的标记系统,例如django-taggit。
答案 2 :(得分:0)
如Chris对回答的评论所述,django-tagging在访问model._tag
时不会传递tagstring。最后,我没有其他解决方案,而是进行查询,然后整理出包含某个标签的循环:
itemlist = list(queryset)
avoid = some_list_of_tag_ids
# search for loops that have NONE of the avoid tags
for item in itemlist:
# has tags and [ if a tag.id in avoid this list has an element]
if (item.tags) and [tag for tag in item.tags if tag.id in avoid]:
# remove the item from the list
itemlist.remove(item)
要完成此模型,请执行以下操作:
class Item(models.Model):
_tags = TagField(blank=True,null=True)
def _get_tags(self):
return Tag.objects.get_for_object(self)
def _set_tags(self, tags):
Tag.objects.update_tags(tags)
tags = property(_get_tags, _set_tags)
尽管我尝试了很长一段时间,但我发现无法将标记标记的查询链接到对象的查询链中。对于这个项目,我坚持使用标记,但这是一个真正的缺点......