我有以下型号:
## Tags for issues
class issueTags(models.Model):
name = models.CharField(max_length=400)
class issues(models.Model):
tags = models.ManyToManyField(issueTags,blank = True)
在我看来,我是从某些客户端JavaScript中获取数组的,即
(Pdb) array_data = request.POST['arr']
(Pdb) array_data
'["2","3"]'
如何过滤我的问题对象以查找与数组中所有标签匹配的所有问题? (2,3是tag__id的ID值。
如果有一种更好的方法来布置也可以工作的对象,那么我可以以此方式进行搜索。
答案 0 :(得分:2)
我还没有测试过,但是我认为您可以执行以下操作:
from django.db.models import Q
array_data = array_data.split(',')
issues.objects.filter(
tags__in=array_data,
).exclude(
# Exclude any that aren't in array_data
~Q(tags__in=array_data)
).annotate(
matches=Count(tags, distinct=True)
).filter(
# Make sure the number found is right.
matches=len(array_data)
)
仅供参考,您应该使用Issue
,IssueTag
作为模型名称,以遵循Django的命名模式。
答案 1 :(得分:0)
这不是最优雅的解决方案或pythonic,但我最终只是在结果过滤器周围循环。
def filter_on_category(issue_object,array_of_tags):
#keep filtering to make an and
i = 0
current_filter = issue_object
while (i < (len(array_of_tags))):
#lets filter again
current_filter=current_filter.filter(tags__id__in=array_of_tags[i])
i=i+1
return current_filter
答案 2 :(得分:0)
多对多字段的Django字段查找参数(__)需要列表参数。我为IssueTags的每个数组元素创建了一个虚拟列表,并将其传递给lookups参数,它可以按预期工作。
让您拥有以下型号:
class IssueTags(models.Model):
name = models.CharField(max_length=400)
class Issues(models.Model):
tags = models.ManyToManyField(IssueTags,blank = True)
您想获取包含所有个IssueTags = [“ 1”,“ 2”,“ 3”]
的问题issue_tags_array = ["1","2","3"]
#First initialize queryset
queryset = Issues.objects.all()
i = 0
while i < len(issue_tags_array):
#dummy issue_tag list
issue_tag = [issue_tags_array[i]]
#lets filter again
queryset = queryset.filter(tags__id__in=issue_tag)
i=i+1
return queryset
答案 3 :(得分:0)
在撰写本文时,现有答案要么不正确(例如过滤匹配具有任何指定标签和正确标签计数的所有问题)或低效(例如在循环中附加过滤器)。
对于以下型号:
class IssueTag(models.Model):
name = models.CharField(max_length=400, blank=True)
class Issue(models.Model):
label = models.CharField(max_length=50, blank=True)
tags = models.ManyToManyField(IssueTag, related_name='issues')
我建议将 Django Annotation 与过滤器结合使用,如下所示:
from django.db.models import Count, Q
tags_to_match = ['tag1', 'tag2']
issues_containing_all_tags = Issue.objects \
.annotate(num_correct_tags=Count('tags',
filter=Q(tags__name__in=tags_to_match))) \
.filter(num_correct_tags=2)
获取具有所有必需标签的所有问题(但可能有其他标签,如问题中所要求的那样)。
这将产生以下 SQL 查询,它解析单个 IN 子句中的所有标记匹配:
SELECT "my_app_issue"."id", "my_app_issue"."label",
COUNT("my_app_issue_tags"."issuetag_id")
FILTER (WHERE "my_app_issuetag"."name" IN ('tag1', 'tag2'))
AS "num_correct_tags"
FROM "my_app_issue"
LEFT OUTER JOIN "my_app_issue_tags" ON ("my_app_issue"."id" = "my_app_issue_tags"."issue_id")
LEFT OUTER JOIN "my_app_issuetag" ON ("my_app_issue_tags"."issuetag_id" = "my_app_issuetag"."id")
GROUP BY "my_app_issue"."id", "my_app_issue"."label"
HAVING COUNT("my_app_issue_tags"."issuetag_id")
FILTER (WHERE ("my_app_issuetag"."name" IN ('tag1', 'tag2'))) = 2;
args=('tag1', 'tag2', 'tag1', 'tag2', 2)