将__icontains查找与django中的__in lookup相结合,以获取包含names数组中name的一部分的对象

时间:2012-03-10 14:19:18

标签: django django-models django-queryset

您好我的模型如下

class Document(models.Model)
    id = models.BigIntegerField(primary_key=True)
    text = models.TextField()

class DocumentTags(models.Model):
    name = model.CharField(max_length=256)
    documents_for_tag = models.ManyToManyField(Document)

现在有了这个,我可以用

获取特定文档的所有标签
parent_document = Document.objects.get(id = 1)
parent_document_tags = [x.name for x in parent_document.documenttags_set.all()]

因此parent_document_tags将包含父文档的所有标记,例如。

["nice" , "unique"]

现在我想接下来让所有Document标签与这个标签列表紧密匹配。我这样做是为了

Document.objects.filter(documenttags__name__in=parent_document_tags).distinct()

但是,这仅匹配parent_document_tags中具有完全名称的文档。我希望与__icontains(或LIKE)匹配相匹配。如何在不拆分我的标签并逐个进行icontains类型查找的情况下执行此操作。

例如。

d1 has tags : "nice", "unique"
d2 has tags :  "nice"
d3 has tags : "nicer"

我希望查询通过将LIKE链接到查找__icontains来返回文档d3以及documenttags__name__in匹配“nicer”。我可以实现这一点,还是我必须有一个for循环并最终过滤掉重复项,如下面的代码所示

related_documents_with_duplicates = []
for tag in parent_document_tags:
    docs = Document.objects.filter(documenttags__name__icontains=tag).distinct()
    related_documents_with_duplicates.extend(docs)
related_documents_id_unique = list(set([x.id for x in related_documents_with_duplicates]))
return Documents.objects.filter(id__in=related_documents_id_unique)

1 个答案:

答案 0 :(得分:0)

实现您想要的方法是使用iregex field lookup

首先,获取所需的标签。而不是做:

parent_document = Document.objects.get(id = 1)
parent_document_tags = [x.name for x in parent_document.documenttags_set.all()]

你可以这样做:

parent_document_tags = DocumentTags.objects.filter(documents_for_tag=1).values_list("name",flat=True)

其次,您将获得一个符合您需要的正则表达式。例如,假设您在parent_document_tags中只有一个名为“tag”的标记。如果我理解你想要什么,你想匹配所有包含(icontains)这个标签的标签的文件。因此,您的查询需要匹配标记为“tag1”标记的文档,“its_a_common_tag”标记...我是对的吗?

因此,这就是如何创建这样的正则表达式(带有正则表达式格式的字符串):

sregex = "|".join(parent_document_tags)
sregex = "(" + sregex + ")"

最后,您想要的查询集如下:

Document.objects.filter(documenttags__name__iregex=sregex)

正则表达式很棒。很难开始使用它们,但是当你了解它们的工作原理时,你将会付出很多努力。

希望它有所帮助!