我定义了3个与M2M关系有关的模型
class Suite(models.Model):
name = models.CharField(max_length=250)
title = models.CharField(max_length=250)
icon = models.CharField(max_length=250)
def __str__(self):
return self.title
class Role(models.Model):
name = models.CharField(max_length=250)
title = models.CharField(max_length=250)
suites = models.ManyToManyField(Suite)
services = models.ManyToManyField(Service)
Actions = models.ManyToManyField(Action)
users = models.ManyToManyField(User)
def __str__(self):
return self.title
Run Code Online (Sandbox Code Playgroud)
在我的一种观点中,我试图收集与特定用户有关的所有Suite。用户可能与可能包含许多Suite的几个Role相关。然后按名称过滤Suite。但是过滤器似乎没有作用
queryset = Suite.objects.union(*(role.suites.all() for role in
self.get_user().role_set.all()))
repr(self.queryset)
'<QuerySet [<Suite: energia>, <Suite: waste 4 thing>]>'
self.queryset = self.queryset.filter(name="energia")
repr(self.queryset)
'<QuerySet [<Suite: energia>, <Suite: waste 4 thing>]>'
Run Code Online (Sandbox Code Playgroud)
在执行过滤器之前,queryset内部的查询属性不会更改其内容:
(SELECT "navbar_suite"."id", "navbar_suite"."name", "navbar_suite"."title", "navbar_suite"."icon" FROM "navbar_suite") UNION (SELECT "navbar_suite"."id", "navbar_suite"."name", "navbar_suite"."title", "navbar_suite"."icon" FROM "navbar_suite" INNER JOIN "navbar_role_suites" ON ("navbar_suite"."id" = "navbar_role_suites"."suite_id") WHERE "navbar_role_suites"."role_id" = 1)
(SELECT "navbar_suite"."id", "navbar_suite"."name", "navbar_suite"."title", "navbar_suite"."icon" FROM "navbar_suite") UNION (SELECT "navbar_suite"."id", "navbar_suite"."name", "navbar_suite"."title", "navbar_suite"."icon" FROM "navbar_suite" INNER JOIN "navbar_role_suites" ON ("navbar_suite"."id" = "navbar_role_suites"."suite_id") WHERE "navbar_role_suites"."role_id" = 1)
Run Code Online (Sandbox Code Playgroud)
正如指出Django文档,只有count(),order_by(),values(),values_list()和工会的查询集的切片是允许的。您无法根据联合查询集进行过滤。
这意味着,您必须在对查询应用联合之前对查询应用过滤器。
此外,您甚至无需使用即可实现目标union():
Suite.objects.filter(role_set__users=self.get_user(), name="energia")
Run Code Online (Sandbox Code Playgroud)
如果您已经使用过模型中的M2M字段related_name或related_query_name定义了suitesM2M字段,则可能需要在过滤器中调整字段名称Role。
小智 8
我遇到了同样的问题,最终使用联合查询作为子查询,以便过滤器可以工作:
yourModelUnionSubQuerySet = YourModelQS1.union(YourModelQS2)
yourModelUnionQuerySet = YourModel.objects.filter(id__in=yourModelUnionSubQuerySet.values('id'))
Run Code Online (Sandbox Code Playgroud)
有一个简单的解决方案。只需使用
self.queryset = self.queryset | <querySet you want to append>
Run Code Online (Sandbox Code Playgroud)
代替
self.queryset = self.queryset.union(<QuerySet you want to append>)
Run Code Online (Sandbox Code Playgroud)
为我工作。我希望这是可以理解的。之后您将能够使用过滤器。
| 归档时间: |
|
| 查看次数: |
1541 次 |
| 最近记录: |