简体   繁体   English

Django 过滤返回空列表的预取查询集

[英]Django filter a prefetched queryset returning an empty list

In my app I have some Users and Groups, that are related by a many to many relation through GroupMember.在我的应用程序中,我有一些用户和组,它们通过 GroupMember 以多对多关系相关。

class User(models.Model):
    ...

class Group(models.Model):
    ...
    users = models.ManyToManyField(User, through='groups.GroupMember', related_name='groups')


class GroupMember(models.Model):
    ...
    user = models.ForeignKey(User, related_name='group_members', on_delete=models.CASCADE)
    group = models.ForeignKey(Group, related_name='members', on_delete=models.CASCADE)

Now I am trying to build an endpoint that retrieves a list of user instances that are in any one of the groups that your user is in. So if user A and B are in group1, user A and C are in group2, and C and D are in group3, retrieving the users as A would return B and C (since those are in groups with A).现在我正在尝试构建一个端点来检索用户所在的任何一个组中的用户实例列表。因此,如果用户 A 和 B 在 group1 中,则用户 A 和 C 在 group2 中,并且 C 和D 在 group3 中,检索用户,因为 A 将返回 B 和 C(因为它们与 A 在组中)。

That filter part can be done in multiple ways, but the part where I am stuck is how to show which groups were the cause of the relation.该过滤器部分可以通过多种方式完成,但我卡住的部分是如何显示哪些组是关系的原因。 I tried to use prefetch_related with a custom filter, to fetch only the groups that have user A in them, like this:我尝试将 prefetch_related 与自定义过滤器一起使用,以仅获取其中包含用户 A 的组,如下所示:

User.objects.exclude(id=user.id).annotate(
    # Annotate the amount of groups related between the users
    related_group_count=Count('groups', filter=Q(groups__users=user))
).filter(
    # Only users that have at least 1 relation with this user
    related_group_count__gt=0
).prefetch_related(
    # Prefetch the specific groups to show
    Prefetch('groups', User.groups.all(), to_attr='related_groups'),
)

The returned users will not have any related_groups , it will be an empty qs.返回的用户不会有任何related_groups ,它将是一个空的 qs。 When I include the request user (by removing the exclude part on the query), the groups will be available for that user, but still not any other.当我包含请求用户(通过删除查询中的排除部分)时,该组可供该用户使用,但仍然不能用于其他任何用户。 This is my current response (including the requesting user "A"):这是我当前的回复(包括请求用户“A”):

{
    "first_name": "A",
    "related_groups": [
        {
            "name": "group1",
        },
        {
            "name": "group2",
        }
    ]
},
{
    "first_name": "B",
    "related_groups": []
},
{
    "first_name": "C",
    "related_groups": []
}

But I'm trying to achieve this:但我正在努力实现这一目标:

{
    "first_name": "B",
    "related_groups": [
        {
            "name": "group1",
        }
    ]
},
{
    "first_name": "C",
    "related_groups": [
        {
            "name": "group2",
        }
    ]
}

The problem lies with the filter on the Prefetch queryset, but I can't figure out what I'm doing wrong or if this is even possible.问题在于 Prefetch 查询集上的过滤器,但我无法弄清楚我做错了什么,或者这是否可能。 I tried different way of filtering (also with Group.objects.filter(users=user) ) or even annotating the group members, counting if the given user is in that group and filtering on that, but with no success...我尝试了不同的过滤方式(也使用Group.objects.filter(users=user) )甚至注释组成员,计算给定用户是否在该组中并对其进行过滤,但没有成功......


Note: This only happens when filtering the prefetch as described above: User (is group member) -> Group -> User (group member).注意:这仅在如上所述过滤预取时发生:用户(是组成员)-> 组 -> 用户(组成员)。 It looks like the filter is "overwriting" the user in the queryset with the initial user (A).看起来过滤器正在用初始用户(A)“覆盖”查询集中的用户。

In my project I work with multiple group-like concepts, one of which has 2 different kind of members (lets say, in context of this question a second GroupMember type model, with an additional many to many relation in the group model to user).在我的项目中,我使用多个类似组的概念,其中一个有 2 种不同类型的成员(可以说,在这个问题的上下文中,第二个 GroupMember 类型 model,在组 model 中与用户有额外的多对多关系) . When using User (group member) -> Group -> User (other kind of member), the prefetch actually works as expected.当使用用户(组成员)-> 组-> 用户(其他类型的成员)时,预取实际上按预期工作。 This issue is only when prefetching using the same through-model in relation to the user.此问题仅在使用与用户相关的相同直通模型进行预取时出现。

I managed to get this to work, by using a separate queryset that gets the group ids.通过使用获取组 ID 的单独查询集,我设法让它工作。 This way the prefetch filter will not use the requesting user id to filter, which resulted in empty lists for all other users.这样,预取过滤器将不会使用请求用户 id 进行过滤,这会导致所有其他用户的列表为空。

group_ids = user.groups.values('pk')

User.objects.exclude(id=user.id).filter(
    groups__in=group_ids
).prefetch_related(
    Prefetch('groups', Group.objects.filter(id__in=group_ids), to_attr='related_groups'),
)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM